New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@effect/ai

Package Overview
Dependencies
Maintainers
0
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@effect/ai - npm Package Compare versions

Comparing version 0.8.1 to 0.8.2

AiTelemetry/package.json

193

dist/cjs/AiChat.js

@@ -32,108 +32,95 @@ "use strict";

exports.AiChat = AiChat;
const fromInput = input => Ref.make(AiInput.make(input)).pipe(Effect.bindTo("historyRef"), Effect.bind("completions", () => _Completions.Completions), Effect.map(({
completions,
historyRef
}) => new AiChatImpl(historyRef, completions)));
exports.fromInput = fromInput;
class AiChatImpl {
historyRef;
completions;
semaphore = /*#__PURE__*/Effect.unsafeMakeSemaphore(1);
constructor(historyRef, completions) {
this.historyRef = historyRef;
this.completions = completions;
}
get history() {
return Ref.get(this.historyRef);
}
get export() {
return Ref.get(this.historyRef).pipe(Effect.flatMap(Schema.encode(AiInput.Schema)), Effect.orDie);
}
get exportJson() {
return Ref.get(this.historyRef).pipe(Effect.flatMap(Schema.encode(AiInput.SchemaJson)), Effect.orDie);
}
send(input) {
const newParts = AiInput.make(input);
return Ref.get(this.historyRef).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return this.completions.create(allParts).pipe(Effect.tap(response => {
const responseParts = AiInput.make(response);
return Ref.set(this.historyRef, Chunk.appendAll(allParts, responseParts));
const fromInput = exports.fromInput = /*#__PURE__*/Effect.fnUntraced(function* (input) {
const completions = yield* _Completions.Completions;
const history = yield* Ref.make(AiInput.make(input));
const semaphore = yield* Effect.makeSemaphore(1);
return AiChat.of({
history: Ref.get(history),
export: Ref.get(history).pipe(Effect.flatMap(Schema.encode(AiInput.Schema)), Effect.orDie),
exportJson: Ref.get(history).pipe(Effect.flatMap(Schema.encode(AiInput.SchemaJson)), Effect.orDie),
send(input) {
const newParts = AiInput.make(input);
return Ref.get(history).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return completions.create(allParts).pipe(Effect.tap(response => {
const responseParts = AiInput.make(response);
return Ref.set(history, Chunk.appendAll(allParts, responseParts));
}));
}), semaphore.withPermits(1), Effect.withSpan("AiChat.send", {
attributes: {
input
},
captureStackTrace: false
}));
}), this.semaphore.withPermits(1), Effect.withSpan("AiChat.send", {
attributes: {
input
},
captureStackTrace: false
}));
}
stream(input) {
return Stream.suspend(() => {
let combined = _AiResponse.AiResponse.empty;
return Stream.fromChannel(Channel.acquireUseRelease(this.semaphore.take(1).pipe(Effect.zipRight(Ref.get(this.historyRef)), Effect.map(Chunk.appendAll(AiInput.make(input)))), parts => this.completions.stream(parts).pipe(Stream.map(chunk => {
combined = combined.concat(chunk);
return chunk;
}), Stream.toChannel), parts => Effect.zipRight(Ref.set(this.historyRef, Chunk.appendAll(parts, AiInput.make(combined))), this.semaphore.release(1))));
}).pipe(Stream.withSpan("AiChat.stream", {
attributes: {
input
},
captureStackTrace: false
}));
}
structured(schema, input) {
const newParts = AiInput.make(input);
return Ref.get(this.historyRef).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return this.completions.structured({
input: allParts,
schema
}).pipe(Effect.flatMap(response => {
const responseParts = AiInput.make(response);
return Effect.as(Ref.set(this.historyRef, Chunk.appendAll(allParts, responseParts)), response.unsafeValue);
},
stream(input) {
return Stream.suspend(() => {
let combined = _AiResponse.AiResponse.empty;
return Stream.fromChannel(Channel.acquireUseRelease(semaphore.take(1).pipe(Effect.zipRight(Ref.get(history)), Effect.map(Chunk.appendAll(AiInput.make(input)))), parts => completions.stream(parts).pipe(Stream.map(chunk => {
combined = combined.concat(chunk);
return chunk;
}), Stream.toChannel), parts => Effect.zipRight(Ref.set(history, Chunk.appendAll(parts, AiInput.make(combined))), semaphore.release(1))));
}).pipe(Stream.withSpan("AiChat.stream", {
attributes: {
input
},
captureStackTrace: false
}));
}), this.semaphore.withPermits(1), Effect.withSpan("AiChat.structured", {
attributes: {
input,
schema: schema._tag ?? schema.identifier
},
captureStackTrace: false
}));
}
toolkit(options) {
const newParts = AiInput.make(options.input);
return Ref.get(this.historyRef).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return this.completions.toolkit({
...options,
input: allParts
}).pipe(Effect.tap(response => {
const responseParts = AiInput.make(response);
return Ref.set(this.historyRef, Chunk.appendAll(allParts, responseParts));
},
structured(options) {
const newParts = AiInput.make(options.input);
return Ref.get(history).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return completions.structured({
...options,
input: allParts
}).pipe(Effect.flatMap(response => {
const responseParts = AiInput.make(response);
return Effect.as(Ref.set(history, Chunk.appendAll(allParts, responseParts)), response.unsafeValue);
}));
}), semaphore.withPermits(1), Effect.withSpan("AiChat.structured", {
attributes: {
input: options.input,
schema: "toolCallId" in options ? options.toolCallId : "_tag" in options.schema ? options.schema._tag : options.schema.identifier
},
captureStackTrace: false
}));
}), this.semaphore.withPermits(1), Effect.withSpan("AiChat.toolkit", {
attributes: {
input: options.input
},
captureStackTrace: false
}));
}
toolkitStream(options) {
return Stream.suspend(() => {
let combined = _AiResponse.WithResolved.empty;
return Stream.fromChannel(Channel.acquireUseRelease(this.semaphore.take(1).pipe(Effect.zipRight(Ref.get(this.historyRef)), Effect.map(Chunk.appendAll(AiInput.make(options.input)))), parts => this.completions.toolkitStream({
...options,
input: parts
}).pipe(Stream.map(chunk => {
combined = combined.concat(chunk);
return chunk;
}), Stream.toChannel), parts => Effect.zipRight(Ref.set(this.historyRef, Chunk.appendAll(parts, AiInput.make(combined))), this.semaphore.release(1))));
}).pipe(Stream.withSpan("AiChat.toolkitStream", {
attributes: {
input: options.input
},
captureStackTrace: false
}));
}
}
},
toolkit(options) {
const newParts = AiInput.make(options.input);
return Ref.get(history).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return completions.toolkit({
...options,
input: allParts
}).pipe(Effect.tap(response => {
const responseParts = AiInput.make(response);
return Ref.set(history, Chunk.appendAll(allParts, responseParts));
}));
}), semaphore.withPermits(1), Effect.withSpan("AiChat.toolkit", {
attributes: {
input: options.input
},
captureStackTrace: false
}));
},
toolkitStream(options) {
return Stream.suspend(() => {
let combined = _AiResponse.WithResolved.empty;
return Stream.fromChannel(Channel.acquireUseRelease(semaphore.take(1).pipe(Effect.zipRight(Ref.get(history)), Effect.map(Chunk.appendAll(AiInput.make(options.input)))), parts => completions.toolkitStream({
...options,
input: parts
}).pipe(Stream.map(chunk => {
combined = combined.concat(chunk);
return chunk;
}), Stream.toChannel), parts => Effect.zipRight(Ref.set(history, Chunk.appendAll(parts, AiInput.make(combined))), semaphore.release(1))));
}).pipe(Stream.withSpan("AiChat.toolkitStream", {
attributes: {
input: options.input
},
captureStackTrace: false
}));
}
});
});
/**

@@ -140,0 +127,0 @@ * @since 1.0.0

@@ -39,32 +39,39 @@ "use strict";

create(input) {
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
return Effect.useSpan("Completions.create", {
captureStackTrace: false
}, span => Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
input: AiInput.make(input),
system: Option.orElse(system, () => parentSystem),
tools: [],
required: false
})), Effect.withSpan("Completions.create", {
captureStackTrace: false
}));
required: false,
span
}))));
},
stream(input_) {
const input = AiInput.make(input_);
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.map(system => options.stream({
return Effect.makeSpanScoped("Completions.stream", {
captureStackTrace: false
}).pipe(Effect.zip(Effect.serviceOption(AiInput.SystemInstruction)), Effect.map(([span, system]) => options.stream({
input: input,
system: Option.orElse(system, () => parentSystem),
tools: [],
required: false
})), Stream.unwrap, Stream.withSpan("Completions.stream", {
captureStackTrace: false
}));
required: false,
span
})), Stream.unwrapScoped);
},
structured(opts) {
const input = AiInput.make(opts.input);
const schema = opts.schema;
const decode = Schema.decodeUnknown(schema);
const toolId = schema._tag ?? schema.identifier;
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
const decode = Schema.decodeUnknown(opts.schema);
const toolId = "toolCallId" in opts ? opts.toolCallId : "_tag" in opts.schema ? opts.schema._tag : opts.schema.identifier;
return Effect.useSpan("Completions.structured", {
attributes: {
toolId
},
captureStackTrace: false
}, span => Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
input: input,
system: Option.orElse(system, () => parentSystem),
tools: [convertTool(schema, true)],
required: true
tools: [convertTool(toolId, opts.schema, true)],
required: true,
span
})), Effect.flatMap(response => Chunk.findFirst(response.parts, part => part._tag === "ToolCall" && part.name === toolId).pipe(Option.match({

@@ -89,8 +96,3 @@ onNone: () => Effect.fail(new _AiError.AiError({

})
}), Effect.withSpan("Completions.structured", {
attributes: {
tool: toolId
},
captureStackTrace: false
}))));
})))));
},

@@ -106,9 +108,16 @@ toolkit({

for (const [, tool] of tools.toolkit.tools) {
toolArr.push(convertTool(tool));
toolArr.push(convertTool(tool._tag, tool));
}
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
return Effect.useSpan("Completions.toolkit", {
attributes: {
concurrency,
required
},
captureStackTrace: false
}, span => Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
input: input,
system: Option.orElse(system, () => parentSystem),
tools: toolArr,
required: required
required: required,
span
})), Effect.flatMap(response => resolveParts({

@@ -119,9 +128,3 @@ response,

method: "toolkit"
})), Effect.withSpan("Completions.toolkit", {
captureStackTrace: false,
attributes: {
concurrency,
required
}
}));
}))));
},

@@ -136,10 +139,17 @@ toolkitStream({

for (const [, tool] of tools.toolkit.tools) {
toolArr.push(convertTool(tool));
toolArr.push(convertTool(tool._tag, tool));
}
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.map(system => options.stream({
return Effect.makeSpanScoped("Completions.stream", {
captureStackTrace: false,
attributes: {
required,
concurrency
}
}).pipe(Effect.zip(Effect.serviceOption(AiInput.SystemInstruction)), Effect.map(([span, system]) => options.stream({
input: AiInput.make(input),
system: Option.orElse(system, () => parentSystem),
tools: toolArr,
required: required
})), Stream.unwrap, Stream.mapEffect(chunk => resolveParts({
required: required,
span
})), Stream.unwrapScoped, Stream.mapEffect(chunk => resolveParts({
response: chunk,

@@ -151,8 +161,2 @@ tools,

concurrency: "unbounded"
}), Stream.withSpan("Completions.toolkitStream", {
captureStackTrace: false,
attributes: {
concurrency,
required
}
}));

@@ -163,6 +167,6 @@ }

exports.make = make;
const convertTool = (tool, structured = false) => ({
name: tool._tag ?? tool.identifier,
description: getDescription(tool.ast),
parameters: makeJsonSchema(tool.ast),
const convertTool = (name, schema, structured = false) => ({
name,
description: getDescription(schema.ast),
parameters: makeJsonSchema(schema.ast),
structured

@@ -169,0 +173,0 @@ });

@@ -6,3 +6,3 @@ "use strict";

});
exports.Tokenizer = exports.Completions = exports.AiToolkit = exports.AiRole = exports.AiResponse = exports.AiInput = exports.AiError = exports.AiChat = void 0;
exports.Tokenizer = exports.Embeddings = exports.Completions = exports.AiToolkit = exports.AiTelemetry = exports.AiRole = exports.AiResponse = exports.AiInput = exports.AiError = exports.AiChat = void 0;
var _AiChat = _interopRequireWildcard(require("./AiChat.js"));

@@ -18,2 +18,4 @@ exports.AiChat = _AiChat;

exports.AiRole = _AiRole;
var _AiTelemetry = _interopRequireWildcard(require("./AiTelemetry.js"));
exports.AiTelemetry = _AiTelemetry;
var _AiToolkit = _interopRequireWildcard(require("./AiToolkit.js"));

@@ -23,2 +25,4 @@ exports.AiToolkit = _AiToolkit;

exports.Completions = _Completions;
var _Embeddings = _interopRequireWildcard(require("./Embeddings.js"));
exports.Embeddings = _Embeddings;
var _Tokenizer = _interopRequireWildcard(require("./Tokenizer.js"));

@@ -25,0 +29,0 @@ exports.Tokenizer = _Tokenizer;

import * as Effect from "effect/Effect";
import type { ParseError } from "effect/ParseResult";
import * as Schema from "effect/Schema";
import * as Stream from "effect/Stream";

@@ -34,3 +35,13 @@ import type { Concurrency } from "effect/Types";

readonly stream: (input: AiInput.Input) => Stream.Stream<AiResponse, AiError>;
readonly structured: <A, I, R>(tool: Completions.StructuredSchema<A, I, R>, input: AiInput.Input) => Effect.Effect<A, AiError, R>;
readonly structured: {
<A, I, R>(options: {
readonly input: AiInput.Input;
readonly schema: Completions.StructuredSchema<A, I, R>;
}): Effect.Effect<A, AiError, R>;
<A, I, R>(options: {
readonly input: AiInput.Input;
readonly schema: Schema.Schema<A, I, R>;
readonly toolCallId: string;
}): Effect.Effect<A, AiError, R>;
};
readonly toolkit: <Tools extends AiToolkit.Tool.AnySchema>(options: {

@@ -37,0 +48,0 @@ readonly input: AiInput.Input;

@@ -11,2 +11,3 @@ /**

import * as Stream from "effect/Stream";
import type { Span } from "effect/Tracer";
import type { Concurrency } from "effect/Types";

@@ -33,6 +34,17 @@ import { AiError } from "./AiError.js";

* @since 1.0.0
* @models
* @category models
*/
interface StructuredSchema<A, I, R> extends Schema.Schema<A, I, R> {
readonly _tag?: string;
type StructuredSchema<A, I, R> = TaggedSchema<A, I, R> | IdentifiedSchema<A, I, R>;
/**
* @since 1.0.0
* @category models
*/
interface TaggedSchema<A, I, R> extends Schema.Schema<A, I, R> {
readonly _tag: string;
}
/**
* @since 1.0.0
* @category models
*/
interface IdentifiedSchema<A, I, R> extends Schema.Schema<A, I, R> {
readonly identifier: string;

@@ -42,3 +54,3 @@ }

* @since 1.0.0
* @models
* @category models
*/

@@ -48,6 +60,13 @@ interface Service {

readonly stream: (input: AiInput.Input) => Stream.Stream<AiResponse, AiError>;
readonly structured: <A, I, R>(options: {
readonly input: AiInput.Input;
readonly schema: StructuredSchema<A, I, R>;
}) => Effect.Effect<WithResolved<A>, AiError, R>;
readonly structured: {
<A, I, R>(options: {
readonly input: AiInput.Input;
readonly schema: StructuredSchema<A, I, R>;
}): Effect.Effect<WithResolved<A>, AiError, R>;
<A, I, R>(options: {
readonly input: AiInput.Input;
readonly schema: Schema.Schema<A, I, R>;
readonly toolCallId: string;
}): Effect.Effect<WithResolved<A>, AiError, R>;
};
readonly toolkit: <Tools extends AiToolkit.Tool.AnySchema>(options: {

@@ -97,2 +116,3 @@ readonly input: AiInput.Input;

readonly required: boolean | string;
readonly span: Span;
}) => Effect.Effect<AiResponse, AiError>;

@@ -109,2 +129,3 @@ readonly stream: (options: {

readonly required: boolean | string;
readonly span: Span;
}) => Stream.Stream<AiResponse, AiError>;

@@ -111,0 +132,0 @@ }) => Effect.Effect<Completions.Service>;

@@ -24,2 +24,6 @@ /**

*/
export * as AiTelemetry from "./AiTelemetry.js";
/**
* @since 1.0.0
*/
export * as AiToolkit from "./AiToolkit.js";

@@ -33,3 +37,7 @@ /**

*/
export * as Embeddings from "./Embeddings.js";
/**
* @since 1.0.0
*/
export * as Tokenizer from "./Tokenizer.js";
//# sourceMappingURL=index.d.ts.map

@@ -22,107 +22,95 @@ /**

*/
export const fromInput = input => Ref.make(AiInput.make(input)).pipe(Effect.bindTo("historyRef"), Effect.bind("completions", () => Completions), Effect.map(({
completions,
historyRef
}) => new AiChatImpl(historyRef, completions)));
class AiChatImpl {
historyRef;
completions;
semaphore = /*#__PURE__*/Effect.unsafeMakeSemaphore(1);
constructor(historyRef, completions) {
this.historyRef = historyRef;
this.completions = completions;
}
get history() {
return Ref.get(this.historyRef);
}
get export() {
return Ref.get(this.historyRef).pipe(Effect.flatMap(Schema.encode(AiInput.Schema)), Effect.orDie);
}
get exportJson() {
return Ref.get(this.historyRef).pipe(Effect.flatMap(Schema.encode(AiInput.SchemaJson)), Effect.orDie);
}
send(input) {
const newParts = AiInput.make(input);
return Ref.get(this.historyRef).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return this.completions.create(allParts).pipe(Effect.tap(response => {
const responseParts = AiInput.make(response);
return Ref.set(this.historyRef, Chunk.appendAll(allParts, responseParts));
export const fromInput = /*#__PURE__*/Effect.fnUntraced(function* (input) {
const completions = yield* Completions;
const history = yield* Ref.make(AiInput.make(input));
const semaphore = yield* Effect.makeSemaphore(1);
return AiChat.of({
history: Ref.get(history),
export: Ref.get(history).pipe(Effect.flatMap(Schema.encode(AiInput.Schema)), Effect.orDie),
exportJson: Ref.get(history).pipe(Effect.flatMap(Schema.encode(AiInput.SchemaJson)), Effect.orDie),
send(input) {
const newParts = AiInput.make(input);
return Ref.get(history).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return completions.create(allParts).pipe(Effect.tap(response => {
const responseParts = AiInput.make(response);
return Ref.set(history, Chunk.appendAll(allParts, responseParts));
}));
}), semaphore.withPermits(1), Effect.withSpan("AiChat.send", {
attributes: {
input
},
captureStackTrace: false
}));
}), this.semaphore.withPermits(1), Effect.withSpan("AiChat.send", {
attributes: {
input
},
captureStackTrace: false
}));
}
stream(input) {
return Stream.suspend(() => {
let combined = AiResponse.empty;
return Stream.fromChannel(Channel.acquireUseRelease(this.semaphore.take(1).pipe(Effect.zipRight(Ref.get(this.historyRef)), Effect.map(Chunk.appendAll(AiInput.make(input)))), parts => this.completions.stream(parts).pipe(Stream.map(chunk => {
combined = combined.concat(chunk);
return chunk;
}), Stream.toChannel), parts => Effect.zipRight(Ref.set(this.historyRef, Chunk.appendAll(parts, AiInput.make(combined))), this.semaphore.release(1))));
}).pipe(Stream.withSpan("AiChat.stream", {
attributes: {
input
},
captureStackTrace: false
}));
}
structured(schema, input) {
const newParts = AiInput.make(input);
return Ref.get(this.historyRef).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return this.completions.structured({
input: allParts,
schema
}).pipe(Effect.flatMap(response => {
const responseParts = AiInput.make(response);
return Effect.as(Ref.set(this.historyRef, Chunk.appendAll(allParts, responseParts)), response.unsafeValue);
},
stream(input) {
return Stream.suspend(() => {
let combined = AiResponse.empty;
return Stream.fromChannel(Channel.acquireUseRelease(semaphore.take(1).pipe(Effect.zipRight(Ref.get(history)), Effect.map(Chunk.appendAll(AiInput.make(input)))), parts => completions.stream(parts).pipe(Stream.map(chunk => {
combined = combined.concat(chunk);
return chunk;
}), Stream.toChannel), parts => Effect.zipRight(Ref.set(history, Chunk.appendAll(parts, AiInput.make(combined))), semaphore.release(1))));
}).pipe(Stream.withSpan("AiChat.stream", {
attributes: {
input
},
captureStackTrace: false
}));
}), this.semaphore.withPermits(1), Effect.withSpan("AiChat.structured", {
attributes: {
input,
schema: schema._tag ?? schema.identifier
},
captureStackTrace: false
}));
}
toolkit(options) {
const newParts = AiInput.make(options.input);
return Ref.get(this.historyRef).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return this.completions.toolkit({
...options,
input: allParts
}).pipe(Effect.tap(response => {
const responseParts = AiInput.make(response);
return Ref.set(this.historyRef, Chunk.appendAll(allParts, responseParts));
},
structured(options) {
const newParts = AiInput.make(options.input);
return Ref.get(history).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return completions.structured({
...options,
input: allParts
}).pipe(Effect.flatMap(response => {
const responseParts = AiInput.make(response);
return Effect.as(Ref.set(history, Chunk.appendAll(allParts, responseParts)), response.unsafeValue);
}));
}), semaphore.withPermits(1), Effect.withSpan("AiChat.structured", {
attributes: {
input: options.input,
schema: "toolCallId" in options ? options.toolCallId : "_tag" in options.schema ? options.schema._tag : options.schema.identifier
},
captureStackTrace: false
}));
}), this.semaphore.withPermits(1), Effect.withSpan("AiChat.toolkit", {
attributes: {
input: options.input
},
captureStackTrace: false
}));
}
toolkitStream(options) {
return Stream.suspend(() => {
let combined = WithResolved.empty;
return Stream.fromChannel(Channel.acquireUseRelease(this.semaphore.take(1).pipe(Effect.zipRight(Ref.get(this.historyRef)), Effect.map(Chunk.appendAll(AiInput.make(options.input)))), parts => this.completions.toolkitStream({
...options,
input: parts
}).pipe(Stream.map(chunk => {
combined = combined.concat(chunk);
return chunk;
}), Stream.toChannel), parts => Effect.zipRight(Ref.set(this.historyRef, Chunk.appendAll(parts, AiInput.make(combined))), this.semaphore.release(1))));
}).pipe(Stream.withSpan("AiChat.toolkitStream", {
attributes: {
input: options.input
},
captureStackTrace: false
}));
}
}
},
toolkit(options) {
const newParts = AiInput.make(options.input);
return Ref.get(history).pipe(Effect.flatMap(parts => {
const allParts = Chunk.appendAll(parts, newParts);
return completions.toolkit({
...options,
input: allParts
}).pipe(Effect.tap(response => {
const responseParts = AiInput.make(response);
return Ref.set(history, Chunk.appendAll(allParts, responseParts));
}));
}), semaphore.withPermits(1), Effect.withSpan("AiChat.toolkit", {
attributes: {
input: options.input
},
captureStackTrace: false
}));
},
toolkitStream(options) {
return Stream.suspend(() => {
let combined = WithResolved.empty;
return Stream.fromChannel(Channel.acquireUseRelease(semaphore.take(1).pipe(Effect.zipRight(Ref.get(history)), Effect.map(Chunk.appendAll(AiInput.make(options.input)))), parts => completions.toolkitStream({
...options,
input: parts
}).pipe(Stream.map(chunk => {
combined = combined.concat(chunk);
return chunk;
}), Stream.toChannel), parts => Effect.zipRight(Ref.set(history, Chunk.appendAll(parts, AiInput.make(combined))), semaphore.release(1))));
}).pipe(Stream.withSpan("AiChat.toolkitStream", {
attributes: {
input: options.input
},
captureStackTrace: false
}));
}
});
});
/**

@@ -129,0 +117,0 @@ * @since 1.0.0

@@ -29,32 +29,39 @@ /**

create(input) {
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
return Effect.useSpan("Completions.create", {
captureStackTrace: false
}, span => Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
input: AiInput.make(input),
system: Option.orElse(system, () => parentSystem),
tools: [],
required: false
})), Effect.withSpan("Completions.create", {
captureStackTrace: false
}));
required: false,
span
}))));
},
stream(input_) {
const input = AiInput.make(input_);
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.map(system => options.stream({
return Effect.makeSpanScoped("Completions.stream", {
captureStackTrace: false
}).pipe(Effect.zip(Effect.serviceOption(AiInput.SystemInstruction)), Effect.map(([span, system]) => options.stream({
input: input,
system: Option.orElse(system, () => parentSystem),
tools: [],
required: false
})), Stream.unwrap, Stream.withSpan("Completions.stream", {
captureStackTrace: false
}));
required: false,
span
})), Stream.unwrapScoped);
},
structured(opts) {
const input = AiInput.make(opts.input);
const schema = opts.schema;
const decode = Schema.decodeUnknown(schema);
const toolId = schema._tag ?? schema.identifier;
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
const decode = Schema.decodeUnknown(opts.schema);
const toolId = "toolCallId" in opts ? opts.toolCallId : "_tag" in opts.schema ? opts.schema._tag : opts.schema.identifier;
return Effect.useSpan("Completions.structured", {
attributes: {
toolId
},
captureStackTrace: false
}, span => Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
input: input,
system: Option.orElse(system, () => parentSystem),
tools: [convertTool(schema, true)],
required: true
tools: [convertTool(toolId, opts.schema, true)],
required: true,
span
})), Effect.flatMap(response => Chunk.findFirst(response.parts, part => part._tag === "ToolCall" && part.name === toolId).pipe(Option.match({

@@ -79,8 +86,3 @@ onNone: () => Effect.fail(new AiError({

})
}), Effect.withSpan("Completions.structured", {
attributes: {
tool: toolId
},
captureStackTrace: false
}))));
})))));
},

@@ -96,9 +98,16 @@ toolkit({

for (const [, tool] of tools.toolkit.tools) {
toolArr.push(convertTool(tool));
toolArr.push(convertTool(tool._tag, tool));
}
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
return Effect.useSpan("Completions.toolkit", {
attributes: {
concurrency,
required
},
captureStackTrace: false
}, span => Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.flatMap(system => options.create({
input: input,
system: Option.orElse(system, () => parentSystem),
tools: toolArr,
required: required
required: required,
span
})), Effect.flatMap(response => resolveParts({

@@ -109,9 +118,3 @@ response,

method: "toolkit"
})), Effect.withSpan("Completions.toolkit", {
captureStackTrace: false,
attributes: {
concurrency,
required
}
}));
}))));
},

@@ -126,10 +129,17 @@ toolkitStream({

for (const [, tool] of tools.toolkit.tools) {
toolArr.push(convertTool(tool));
toolArr.push(convertTool(tool._tag, tool));
}
return Effect.serviceOption(AiInput.SystemInstruction).pipe(Effect.map(system => options.stream({
return Effect.makeSpanScoped("Completions.stream", {
captureStackTrace: false,
attributes: {
required,
concurrency
}
}).pipe(Effect.zip(Effect.serviceOption(AiInput.SystemInstruction)), Effect.map(([span, system]) => options.stream({
input: AiInput.make(input),
system: Option.orElse(system, () => parentSystem),
tools: toolArr,
required: required
})), Stream.unwrap, Stream.mapEffect(chunk => resolveParts({
required: required,
span
})), Stream.unwrapScoped, Stream.mapEffect(chunk => resolveParts({
response: chunk,

@@ -141,8 +151,2 @@ tools,

concurrency: "unbounded"
}), Stream.withSpan("Completions.toolkitStream", {
captureStackTrace: false,
attributes: {
concurrency,
required
}
}));

@@ -152,6 +156,6 @@ }

});
const convertTool = (tool, structured = false) => ({
name: tool._tag ?? tool.identifier,
description: getDescription(tool.ast),
parameters: makeJsonSchema(tool.ast),
const convertTool = (name, schema, structured = false) => ({
name,
description: getDescription(schema.ast),
parameters: makeJsonSchema(schema.ast),
structured

@@ -158,0 +162,0 @@ });

@@ -24,2 +24,6 @@ /**

*/
export * as AiTelemetry from "./AiTelemetry.js";
/**
* @since 1.0.0
*/
export * as AiToolkit from "./AiToolkit.js";

@@ -33,3 +37,7 @@ /**

*/
export * as Embeddings from "./Embeddings.js";
/**
* @since 1.0.0
*/
export * as Tokenizer from "./Tokenizer.js";
//# sourceMappingURL=index.js.map
{
"name": "@effect/ai",
"version": "0.8.1",
"version": "0.8.2",
"description": "Effect modules for working with AI apis",

@@ -14,4 +14,5 @@ "license": "MIT",

"peerDependencies": {
"@effect/platform": "^0.75.1",
"effect": "^3.12.7"
"@effect/experimental": "^0.39.2",
"@effect/platform": "^0.75.2",
"effect": "^3.12.8"
},

@@ -56,2 +57,7 @@ "publishConfig": {

},
"./AiTelemetry": {
"types": "./dist/dts/AiTelemetry.d.ts",
"import": "./dist/esm/AiTelemetry.js",
"default": "./dist/cjs/AiTelemetry.js"
},
"./AiToolkit": {

@@ -67,2 +73,7 @@ "types": "./dist/dts/AiToolkit.d.ts",

},
"./Embeddings": {
"types": "./dist/dts/Embeddings.d.ts",
"import": "./dist/esm/Embeddings.js",
"default": "./dist/cjs/Embeddings.js"
},
"./Tokenizer": {

@@ -91,2 +102,5 @@ "types": "./dist/dts/Tokenizer.d.ts",

],
"AiTelemetry": [
"./dist/dts/AiTelemetry.d.ts"
],
"AiToolkit": [

@@ -98,2 +112,5 @@ "./dist/dts/AiToolkit.d.ts"

],
"Embeddings": [
"./dist/dts/Embeddings.d.ts"
],
"Tokenizer": [

@@ -100,0 +117,0 @@ "./dist/dts/Tokenizer.d.ts"

@@ -42,6 +42,13 @@ /**

readonly stream: (input: AiInput.Input) => Stream.Stream<AiResponse, AiError>
readonly structured: <A, I, R>(
tool: Completions.StructuredSchema<A, I, R>,
input: AiInput.Input
) => Effect.Effect<A, AiError, R>
readonly structured: {
<A, I, R>(options: {
readonly input: AiInput.Input
readonly schema: Completions.StructuredSchema<A, I, R>
}): Effect.Effect<A, AiError, R>
<A, I, R>(options: {
readonly input: AiInput.Input
readonly schema: Schema.Schema<A, I, R>
readonly toolCallId: string
}): Effect.Effect<A, AiError, R>
}
readonly toolkit: <Tools extends AiToolkit.Tool.AnySchema>(

@@ -78,177 +85,161 @@ options: {

*/
export const fromInput = (input: AiInput.Input): Effect.Effect<AiChat.Service, never, Completions> =>
Ref.make(AiInput.make(input)).pipe(
Effect.bindTo("historyRef"),
Effect.bind("completions", () => Completions),
Effect.map(({ completions, historyRef }) => new AiChatImpl(historyRef, completions))
)
export const fromInput = Effect.fnUntraced(
function*(input: AiInput.Input) {
const completions = yield* Completions
const history = yield* Ref.make(AiInput.make(input))
const semaphore = yield* Effect.makeSemaphore(1)
class AiChatImpl implements AiChat.Service {
readonly semaphore = Effect.unsafeMakeSemaphore(1)
constructor(
readonly historyRef: Ref.Ref<AiInput.AiInput>,
readonly completions: Completions.Service
) {}
get history() {
return Ref.get(this.historyRef)
}
get export() {
return Ref.get(this.historyRef).pipe(
Effect.flatMap(Schema.encode(AiInput.Schema)),
Effect.orDie
)
}
get exportJson() {
return Ref.get(this.historyRef).pipe(
Effect.flatMap(Schema.encode(AiInput.SchemaJson)),
Effect.orDie
)
}
send(input: AiInput.Input) {
const newParts = AiInput.make(input)
return Ref.get(this.historyRef).pipe(
Effect.flatMap((parts) => {
const allParts = Chunk.appendAll(parts, newParts)
return this.completions.create(allParts).pipe(
Effect.tap((response) => {
const responseParts = AiInput.make(response)
return Ref.set(this.historyRef, Chunk.appendAll(allParts, responseParts))
return AiChat.of({
history: Ref.get(history),
export: Ref.get(history).pipe(
Effect.flatMap(Schema.encode(AiInput.Schema)),
Effect.orDie
),
exportJson: Ref.get(history).pipe(
Effect.flatMap(Schema.encode(AiInput.SchemaJson)),
Effect.orDie
),
send(input) {
const newParts = AiInput.make(input)
return Ref.get(history).pipe(
Effect.flatMap((parts) => {
const allParts = Chunk.appendAll(parts, newParts)
return completions.create(allParts).pipe(
Effect.tap((response) => {
const responseParts = AiInput.make(response)
return Ref.set(history, Chunk.appendAll(allParts, responseParts))
})
)
}),
semaphore.withPermits(1),
Effect.withSpan("AiChat.send", {
attributes: { input },
captureStackTrace: false
})
)
}),
this.semaphore.withPermits(1),
Effect.withSpan("AiChat.send", { attributes: { input }, captureStackTrace: false })
)
}
stream(input: AiInput.Input) {
return Stream.suspend(() => {
let combined = AiResponse.empty
return Stream.fromChannel(Channel.acquireUseRelease(
this.semaphore.take(1).pipe(
Effect.zipRight(Ref.get(this.historyRef)),
Effect.map(Chunk.appendAll(AiInput.make(input)))
),
(parts) =>
this.completions.stream(parts).pipe(
Stream.map((chunk) => {
combined = combined.concat(chunk)
return chunk
}),
Stream.toChannel
),
(parts) =>
Effect.zipRight(
Ref.set(this.historyRef, Chunk.appendAll(parts, AiInput.make(combined))),
this.semaphore.release(1)
)
))
}).pipe(Stream.withSpan("AiChat.stream", { attributes: { input }, captureStackTrace: false }))
}
structured<A, I, R>(
schema: Completions.StructuredSchema<A, I, R>,
input: AiInput.Input
): Effect.Effect<A, AiError, R> {
const newParts = AiInput.make(input)
return Ref.get(this.historyRef).pipe(
Effect.flatMap((parts) => {
const allParts = Chunk.appendAll(parts, newParts)
return this.completions.structured({
input: allParts,
schema
}).pipe(
Effect.flatMap((response) => {
const responseParts = AiInput.make(response)
return Effect.as(
Ref.set(this.historyRef, Chunk.appendAll(allParts, responseParts)),
response.unsafeValue
},
stream(input) {
return Stream.suspend(() => {
let combined = AiResponse.empty
return Stream.fromChannel(Channel.acquireUseRelease(
semaphore.take(1).pipe(
Effect.zipRight(Ref.get(history)),
Effect.map(Chunk.appendAll(AiInput.make(input)))
),
(parts) =>
completions.stream(parts).pipe(
Stream.map((chunk) => {
combined = combined.concat(chunk)
return chunk
}),
Stream.toChannel
),
(parts) =>
Effect.zipRight(
Ref.set(history, Chunk.appendAll(parts, AiInput.make(combined))),
semaphore.release(1)
)
))
}).pipe(Stream.withSpan("AiChat.stream", {
attributes: { input },
captureStackTrace: false
}))
},
structured(options) {
const newParts = AiInput.make(options.input)
return Ref.get(history).pipe(
Effect.flatMap((parts) => {
const allParts = Chunk.appendAll(parts, newParts)
return completions.structured({
...options,
input: allParts
} as any).pipe(
Effect.flatMap((response) => {
const responseParts = AiInput.make(response)
return Effect.as(
Ref.set(history, Chunk.appendAll(allParts, responseParts)),
response.unsafeValue
)
})
)
}),
semaphore.withPermits(1),
Effect.withSpan("AiChat.structured", {
attributes: {
input: options.input,
schema: "toolCallId" in options
? options.toolCallId
: "_tag" in options.schema
? options.schema._tag
: options.schema.identifier
},
captureStackTrace: false
})
)
}),
this.semaphore.withPermits(1),
Effect.withSpan("AiChat.structured", {
attributes: { input, schema: schema._tag ?? schema.identifier },
captureStackTrace: false
})
)
}
toolkit<Tools extends AiToolkit.Tool.AnySchema>(
options: {
readonly input: AiInput.Input
readonly tools: AiToolkit.Handlers<Tools>
readonly required?: Tools["_tag"] | boolean | undefined
readonly concurrency?: Concurrency | undefined
}
): Effect.Effect<
WithResolved<AiToolkit.Tool.Success<Tools>>,
AiError | AiToolkit.Tool.Failure<Tools>,
AiToolkit.Tool.Context<Tools>
> {
const newParts = AiInput.make(options.input)
return Ref.get(this.historyRef).pipe(
Effect.flatMap((parts) => {
const allParts = Chunk.appendAll(parts, newParts)
return this.completions.toolkit({
...options,
input: allParts
}).pipe(
Effect.tap((response) => {
const responseParts = AiInput.make(response)
return Ref.set(this.historyRef, Chunk.appendAll(allParts, responseParts))
},
toolkit(options) {
const newParts = AiInput.make(options.input)
return Ref.get(history).pipe(
Effect.flatMap((parts) => {
const allParts = Chunk.appendAll(parts, newParts)
return completions.toolkit({
...options,
input: allParts
}).pipe(
Effect.tap((response) => {
const responseParts = AiInput.make(response)
return Ref.set(history, Chunk.appendAll(allParts, responseParts))
})
)
}),
semaphore.withPermits(1),
Effect.withSpan("AiChat.toolkit", {
attributes: { input: options.input },
captureStackTrace: false
})
)
}),
this.semaphore.withPermits(1),
Effect.withSpan("AiChat.toolkit", { attributes: { input: options.input }, captureStackTrace: false })
)
},
toolkitStream<Tools extends AiToolkit.Tool.AnySchema>(options: {
readonly input: AiInput.Input
readonly tools: AiToolkit.Handlers<Tools>
readonly required?: Tools["_tag"] | boolean | undefined
readonly concurrency?: Concurrency | undefined
}): Stream.Stream<
WithResolved<AiToolkit.Tool.Success<Tools>>,
AiError | AiToolkit.Tool.Failure<Tools>,
AiToolkit.Tool.Context<Tools>
> {
return Stream.suspend(() => {
let combined = WithResolved.empty as WithResolved<AiToolkit.Tool.Success<Tools>>
return Stream.fromChannel(Channel.acquireUseRelease(
semaphore.take(1).pipe(
Effect.zipRight(Ref.get(history)),
Effect.map(Chunk.appendAll(AiInput.make(options.input)))
),
(parts) =>
completions.toolkitStream({
...options,
input: parts
}).pipe(
Stream.map((chunk) => {
combined = combined.concat(chunk)
return chunk
}),
Stream.toChannel
),
(parts) =>
Effect.zipRight(
Ref.set(history, Chunk.appendAll(parts, AiInput.make(combined))),
semaphore.release(1)
)
))
}).pipe(Stream.withSpan("AiChat.toolkitStream", {
attributes: { input: options.input },
captureStackTrace: false
}))
}
})
}
)
toolkitStream<Tools extends AiToolkit.Tool.AnySchema>(
options: {
readonly input: AiInput.Input
readonly tools: AiToolkit.Handlers<Tools>
readonly required?: Tools["_tag"] | boolean | undefined
readonly concurrency?: Concurrency | undefined
}
): Stream.Stream<
WithResolved<AiToolkit.Tool.Success<Tools>>,
AiError | AiToolkit.Tool.Failure<Tools>,
AiToolkit.Tool.Context<Tools>
> {
return Stream.suspend(() => {
let combined = WithResolved.empty as WithResolved<AiToolkit.Tool.Success<Tools>>
return Stream.fromChannel(Channel.acquireUseRelease(
this.semaphore.take(1).pipe(
Effect.zipRight(Ref.get(this.historyRef)),
Effect.map(Chunk.appendAll(AiInput.make(options.input)))
),
(parts) =>
this.completions.toolkitStream({
...options,
input: parts
}).pipe(
Stream.map((chunk) => {
combined = combined.concat(chunk)
return chunk
}),
Stream.toChannel
),
(parts) =>
Effect.zipRight(
Ref.set(this.historyRef, Chunk.appendAll(parts, AiInput.make(combined))),
this.semaphore.release(1)
)
))
}).pipe(Stream.withSpan("AiChat.toolkitStream", { attributes: { input: options.input }, captureStackTrace: false }))
}
}
/**

@@ -255,0 +246,0 @@ * @since 1.0.0

@@ -13,2 +13,3 @@ /**

import * as Stream from "effect/Stream"
import type { Span } from "effect/Tracer"
import type { Concurrency } from "effect/Types"

@@ -38,6 +39,19 @@ import { AiError } from "./AiError.js"

* @since 1.0.0
* @models
* @category models
*/
export interface StructuredSchema<A, I, R> extends Schema.Schema<A, I, R> {
readonly _tag?: string
export type StructuredSchema<A, I, R> = TaggedSchema<A, I, R> | IdentifiedSchema<A, I, R>
/**
* @since 1.0.0
* @category models
*/
export interface TaggedSchema<A, I, R> extends Schema.Schema<A, I, R> {
readonly _tag: string
}
/**
* @since 1.0.0
* @category models
*/
export interface IdentifiedSchema<A, I, R> extends Schema.Schema<A, I, R> {
readonly identifier: string

@@ -48,3 +62,3 @@ }

* @since 1.0.0
* @models
* @category models
*/

@@ -54,8 +68,13 @@ export interface Service {

readonly stream: (input: AiInput.Input) => Stream.Stream<AiResponse, AiError>
readonly structured: <A, I, R>(
options: {
readonly structured: {
<A, I, R>(options: {
readonly input: AiInput.Input
readonly schema: StructuredSchema<A, I, R>
}
) => Effect.Effect<WithResolved<A>, AiError, R>
}): Effect.Effect<WithResolved<A>, AiError, R>
<A, I, R>(options: {
readonly input: AiInput.Input
readonly schema: Schema.Schema<A, I, R>
readonly toolCallId: string
}): Effect.Effect<WithResolved<A>, AiError, R>
}
readonly toolkit: <Tools extends AiToolkit.Tool.AnySchema>(

@@ -121,2 +140,3 @@ options: {

readonly required: boolean | string
readonly span: Span
}) => Effect.Effect<AiResponse, AiError>

@@ -133,2 +153,3 @@ readonly stream: (options: {

readonly required: boolean | string
readonly span: Span
}) => Stream.Stream<AiResponse, AiError>

@@ -139,12 +160,17 @@ }): Effect.Effect<Completions.Service> =>

create(input) {
return Effect.serviceOption(AiInput.SystemInstruction).pipe(
Effect.flatMap((system) =>
options.create({
input: AiInput.make(input) as Chunk.NonEmptyChunk<Message>,
system: Option.orElse(system, () => parentSystem),
tools: [],
required: false
})
),
Effect.withSpan("Completions.create", { captureStackTrace: false })
return Effect.useSpan(
"Completions.create",
{ captureStackTrace: false },
(span) =>
Effect.serviceOption(AiInput.SystemInstruction).pipe(
Effect.flatMap((system) =>
options.create({
input: AiInput.make(input) as Chunk.NonEmptyChunk<Message>,
system: Option.orElse(system, () => parentSystem),
tools: [],
required: false,
span
})
)
)
)

@@ -154,4 +180,5 @@ },

const input = AiInput.make(input_)
return Effect.serviceOption(AiInput.SystemInstruction).pipe(
Effect.map((system) =>
return Effect.makeSpanScoped("Completions.stream", { captureStackTrace: false }).pipe(
Effect.zip(Effect.serviceOption(AiInput.SystemInstruction)),
Effect.map(([span, system]) =>
options.stream({

@@ -161,7 +188,7 @@ input: input as Chunk.NonEmptyChunk<Message>,

tools: [],
required: false
required: false,
span
})
),
Stream.unwrap,
Stream.withSpan("Completions.stream", { captureStackTrace: false })
Stream.unwrapScoped
)

@@ -171,53 +198,58 @@ },

const input = AiInput.make(opts.input)
const schema = opts.schema
const decode = Schema.decodeUnknown(schema)
const toolId = schema._tag ?? schema.identifier
return Effect.serviceOption(AiInput.SystemInstruction).pipe(
Effect.flatMap((system) =>
options.create({
input: input as Chunk.NonEmptyChunk<Message>,
system: Option.orElse(system, () => parentSystem),
tools: [convertTool(schema, true)],
required: true
})
),
Effect.flatMap((response) =>
Chunk.findFirst(
response.parts,
(part): part is ToolCallPart => part._tag === "ToolCall" && part.name === toolId
).pipe(
Option.match({
onNone: () =>
Effect.fail(
new AiError({
module: "Completions",
method: "structured",
description: `Tool call '${toolId}' not found in response`
})
),
onSome: (toolCall) =>
Effect.matchEffect(decode(toolCall.params), {
onFailure: (cause) =>
new AiError({
module: "Completions",
method: "structured",
description: `Failed to decode tool call '${toolId}' parameters`,
cause
}),
onSuccess: (resolved) =>
Effect.succeed(
new WithResolved({
response,
resolved: new Map([[toolCall.id, resolved]]),
encoded: new Map([[toolCall.id, toolCall.params]])
const decode = Schema.decodeUnknown(opts.schema)
const toolId = "toolCallId" in opts
? opts.toolCallId
: "_tag" in opts.schema
? opts.schema._tag
: opts.schema.identifier
return Effect.useSpan(
"Completions.structured",
{ attributes: { toolId }, captureStackTrace: false },
(span) =>
Effect.serviceOption(AiInput.SystemInstruction).pipe(
Effect.flatMap((system) =>
options.create({
input: input as Chunk.NonEmptyChunk<Message>,
system: Option.orElse(system, () => parentSystem),
tools: [convertTool(toolId, opts.schema, true)],
required: true,
span
})
),
Effect.flatMap((response) =>
Chunk.findFirst(
response.parts,
(part): part is ToolCallPart => part._tag === "ToolCall" && part.name === toolId
).pipe(
Option.match({
onNone: () =>
Effect.fail(
new AiError({
module: "Completions",
method: "structured",
description: `Tool call '${toolId}' not found in response`
})
)
),
onSome: (toolCall) =>
Effect.matchEffect(decode(toolCall.params), {
onFailure: (cause) =>
new AiError({
module: "Completions",
method: "structured",
description: `Failed to decode tool call '${toolId}' parameters`,
cause
}),
onSuccess: (resolved) =>
Effect.succeed(
new WithResolved({
response,
resolved: new Map([[toolCall.id, resolved]]),
encoded: new Map([[toolCall.id, toolCall.params]])
})
)
})
})
}),
Effect.withSpan("Completions.structured", {
attributes: { tool: toolId },
captureStackTrace: false
})
)
)
)
)
)

@@ -234,22 +266,21 @@ },

for (const [, tool] of tools.toolkit.tools) {
toolArr.push(convertTool(tool as any))
toolArr.push(convertTool(tool._tag, tool as any))
}
return Effect.serviceOption(AiInput.SystemInstruction).pipe(
Effect.flatMap((system) =>
options.create({
input: input as Chunk.NonEmptyChunk<Message>,
system: Option.orElse(system, () => parentSystem),
tools: toolArr,
required: required as any
})
),
Effect.flatMap((response) => resolveParts({ response, tools, concurrency, method: "toolkit" })),
Effect.withSpan("Completions.toolkit", {
captureStackTrace: false,
attributes: {
concurrency,
required
}
})
) as any
return Effect.useSpan(
"Completions.toolkit",
{ attributes: { concurrency, required }, captureStackTrace: false },
(span) =>
Effect.serviceOption(AiInput.SystemInstruction).pipe(
Effect.flatMap((system) =>
options.create({
input: input as Chunk.NonEmptyChunk<Message>,
system: Option.orElse(system, () => parentSystem),
tools: toolArr,
required: required as any,
span
})
),
Effect.flatMap((response) => resolveParts({ response, tools, concurrency, method: "toolkit" }))
) as any
)
},

@@ -264,6 +295,10 @@ toolkitStream({ concurrency, input, required = false, tools }) {

for (const [, tool] of tools.toolkit.tools) {
toolArr.push(convertTool(tool as any))
toolArr.push(convertTool(tool._tag, tool as any))
}
return Effect.serviceOption(AiInput.SystemInstruction).pipe(
Effect.map((system) =>
return Effect.makeSpanScoped("Completions.stream", {
captureStackTrace: false,
attributes: { required, concurrency }
}).pipe(
Effect.zip(Effect.serviceOption(AiInput.SystemInstruction)),
Effect.map(([span, system]) =>
options.stream({

@@ -273,17 +308,11 @@ input: AiInput.make(input) as Chunk.NonEmptyChunk<Message>,

tools: toolArr,
required: required as any
required: required as any,
span
})
),
Stream.unwrap,
Stream.unwrapScoped,
Stream.mapEffect(
(chunk) => resolveParts({ response: chunk, tools, concurrency, method: "toolkitStream" }),
{ concurrency: "unbounded" }
),
Stream.withSpan("Completions.toolkitStream", {
captureStackTrace: false,
attributes: {
concurrency,
required
}
})
)
) as any

@@ -294,6 +323,10 @@ }

const convertTool = <A, I, R>(tool: Completions.StructuredSchema<A, I, R>, structured = false) => ({
name: tool._tag ?? tool.identifier,
description: getDescription(tool.ast),
parameters: makeJsonSchema(tool.ast),
const convertTool = <A, I, R>(
name: string,
schema: Schema.Schema<A, I, R>,
structured = false
) => ({
name,
description: getDescription(schema.ast),
parameters: makeJsonSchema(schema.ast),
structured

@@ -300,0 +333,0 @@ })

@@ -29,2 +29,7 @@ /**

*/
export * as AiTelemetry from "./AiTelemetry.js"
/**
* @since 1.0.0
*/
export * as AiToolkit from "./AiToolkit.js"

@@ -40,2 +45,7 @@

*/
export * as Embeddings from "./Embeddings.js"
/**
* @since 1.0.0
*/
export * as Tokenizer from "./Tokenizer.js"

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc