Skip to content

Commit

Permalink
refactor: define interface types for the new runtime API (#940)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yonom authored Oct 2, 2024
1 parent 1d27b55 commit 2b7c6fe
Show file tree
Hide file tree
Showing 17 changed files with 354 additions and 61 deletions.
5 changes: 5 additions & 0 deletions .changeset/yellow-mangos-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@assistant-ui/react": patch
---

refactor: define interface types for the new runtime API
9 changes: 5 additions & 4 deletions packages/react-playground/src/lib/playground-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ const {
ProxyConfigProvider,
generateId,
DefaultThreadComposerRuntimeCore,
AssistantRuntime,
ThreadRuntime,
AssistantRuntimeImpl,
ThreadRuntimeImpl,
} = INTERNAL;

const makeModelConfigStore = () =>
Expand Down Expand Up @@ -108,6 +108,7 @@ export class PlaygroundThreadRuntimeCore implements INTERNAL.ThreadRuntimeCore {
public readonly threadId = generateId();
public readonly isDisabled = false;
public readonly capabilities = CAPABILITIES;
public readonly extras = undefined;

private configProvider = new ProxyConfigProvider();

Expand Down Expand Up @@ -504,7 +505,7 @@ export class PlaygroundThreadRuntimeCore implements INTERNAL.ThreadRuntimeCore {
}
}

class PlaygroundThreadRuntime extends ThreadRuntime {
class PlaygroundThreadRuntime extends ThreadRuntimeImpl {
constructor(private binding: INTERNAL.ThreadRuntimeCoreBinding) {
super(binding);
}
Expand Down Expand Up @@ -532,7 +533,7 @@ export const usePlaygroundRuntime = ({
);

return useMemo(
() => new AssistantRuntime(runtime, PlaygroundThreadRuntime),
() => new AssistantRuntimeImpl(runtime, PlaygroundThreadRuntime),
[runtime],
);
};
27 changes: 24 additions & 3 deletions packages/react/src/api/AssistantRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,31 @@ import { AssistantRuntimeCore } from "../runtimes/core/AssistantRuntimeCore";
import { NestedSubscriptionSubject } from "./subscribable/NestedSubscriptionSubject";
import { ModelConfigProvider } from "../types/ModelConfigTypes";
import { ThreadRuntime, ThreadRuntimeCoreBinding } from "./ThreadRuntime";
import { Unsubscribe } from "../types";

export class AssistantRuntime<
TThreadRuntime extends ThreadRuntime = ThreadRuntime,
> implements AssistantRuntimeCore
export type AssistantRuntime = {
thread: ThreadRuntime;

switchToNewThread(): void;

switchToThread(threadId: string): void;
/**
* @deprecated Use `switchToNewThread` instead. This will be removed in 0.6.0.
*/
switchToThread(threadId: string | null): void;

registerModelConfigProvider(provider: ModelConfigProvider): Unsubscribe;

/**
* @deprecated Thread is now static and never gets updated. This will be removed in 0.6.0.
*/
subscribe(callback: () => void): Unsubscribe;
};

export class AssistantRuntimeImpl<
TThreadRuntime extends ThreadRuntime = ThreadRuntime,
>
implements AssistantRuntimeCore, AssistantRuntime
{
constructor(
private _core: AssistantRuntimeCore,
Expand Down
29 changes: 22 additions & 7 deletions packages/react/src/api/AttachmentRuntime.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { SubscribableWithState } from "./subscribable/Subscribable";

import { ComposerRuntimeCoreBinding } from "./ComposerRuntime";
import { Attachment, CompleteAttachment, PendingAttachment } from "../types";
import {
Attachment,
CompleteAttachment,
PendingAttachment,
Unsubscribe,
} from "../types";

type MessageAttachmentState = CompleteAttachment & {
source: "message";
Expand Down Expand Up @@ -37,9 +42,19 @@ type AttachmentSnapshotBinding<Source extends AttachmentRuntimeSource> =

type AttachmentRuntimeSource = AttachmentState["source"];

export abstract class AttachmentRuntime<
export type AttachmentRuntime<
TSource extends AttachmentRuntimeSource = AttachmentRuntimeSource,
> = {
readonly source: TSource;
getState(): AttachmentState & { source: TSource };
remove(): Promise<void>;
subscribe(callback: () => void): Unsubscribe;
};

export abstract class AttachmentRuntimeImpl<
Source extends AttachmentRuntimeSource = AttachmentRuntimeSource,
> {
> implements AttachmentRuntime
{
public abstract get source(): Source;

constructor(private _core: AttachmentSnapshotBinding<Source>) {}
Expand All @@ -57,7 +72,7 @@ export abstract class AttachmentRuntime<

abstract class ComposerAttachmentRuntime<
Source extends "thread-composer" | "edit-composer",
> extends AttachmentRuntime<Source> {
> extends AttachmentRuntimeImpl<Source> {
constructor(
core: AttachmentSnapshotBinding<Source>,
private _composerApi: ComposerRuntimeCoreBinding,
Expand All @@ -72,19 +87,19 @@ abstract class ComposerAttachmentRuntime<
}
}

export class ThreadComposerAttachmentRuntime extends ComposerAttachmentRuntime<"thread-composer"> {
export class ThreadComposerAttachmentRuntimeImpl extends ComposerAttachmentRuntime<"thread-composer"> {
public get source(): "thread-composer" {
return "thread-composer";
}
}

export class EditComposerAttachmentRuntime extends ComposerAttachmentRuntime<"edit-composer"> {
export class EditComposerAttachmentRuntimeImpl extends ComposerAttachmentRuntime<"edit-composer"> {
public get source(): "edit-composer" {
return "edit-composer";
}
}

export class MessageAttachmentRuntime extends AttachmentRuntime<"message"> {
export class MessageAttachmentRuntimeImpl extends AttachmentRuntimeImpl<"message"> {
public get source(): "message" {
return "message";
}
Expand Down
113 changes: 99 additions & 14 deletions packages/react/src/api/ComposerRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { LazyMemoizeSubject } from "./subscribable/LazyMemoizeSubject";
import {
AttachmentRuntime,
AttachmentState,
EditComposerAttachmentRuntime,
ThreadComposerAttachmentRuntime,
EditComposerAttachmentRuntimeImpl,
ThreadComposerAttachmentRuntimeImpl,
} from "./AttachmentRuntime";
import { ShallowMemoizeSubject } from "./subscribable/ShallowMemoizeSubject";
import { SKIP_UPDATE } from "./subscribable/SKIP_UPDATE";
Expand Down Expand Up @@ -178,7 +178,50 @@ const getEditComposerState = (
});
};

export abstract class ComposerRuntime implements ComposerRuntimeCore {
export type ComposerRuntime = {
readonly type: "edit" | "thread";
getState(): ComposerState;

/** @deprecated Use `getState().isEditing` instead. This will be removed in 0.6.0. */
readonly isEditing: boolean;

/** @deprecated Use `getState().isEmpty` instead. This will be removed in 0.6.0. */
readonly isEmpty: boolean;

/** @deprecated Use `getState().canCancel` instead. This will be removed in 0.6.0. */
readonly canCancel: boolean;

/** @deprecated Use `getState().text` instead. This will be removed in 0.6.0. */
readonly text: string;

/** @deprecated Use `getState().attachmentAccept` instead. This will be removed in 0.6.0. */
readonly attachmentAccept: string;

/** @deprecated Use `getState().attachments` instead. This will be removed in 0.6.0. */
readonly attachments: readonly Attachment[];

/** @deprecated Use `getState().text` instead. This will be removed in 0.6.0. */
readonly value: string;

setText(text: string): void;
setValue(text: string): void;
addAttachment(file: File): void;

/** @deprecated Use `getAttachmentById(id).removeAttachment()` instead. This will be removed in 0.6.0. */
removeAttachment(attachmentId: string): void;

/** @deprecated This method will be removed in 0.6.0. Submit feedback if you need this functionality. */
reset(): void;

send(): void;
cancel(): void;
subscribe(callback: () => void): Unsubscribe;
getAttachmentByIndex(idx: number): AttachmentRuntime;
};

export abstract class ComposerRuntimeImpl
implements ComposerRuntimeCore, ComposerRuntime
{
public abstract get type(): "edit" | "thread";

constructor(protected _core: ComposerRuntimeCoreBinding) {}
Expand Down Expand Up @@ -250,9 +293,9 @@ export abstract class ComposerRuntime implements ComposerRuntimeCore {
return core.addAttachment(file);
}

// /**
// * @deprecated Use `getAttachmentById(id).removeAttachment` instead. This will be removed in 0.6.0.
// */
/**
* @deprecated Use `getAttachmentById(id).removeAttachment()` instead. This will be removed in 0.6.0.
*/
public removeAttachment(attachmentId: string) {
const core = this._core.getState();
if (!core) throw new Error("Composer is not available");
Expand Down Expand Up @@ -287,9 +330,27 @@ export abstract class ComposerRuntime implements ComposerRuntimeCore {
public abstract getAttachmentByIndex(idx: number): AttachmentRuntime;
}

export class ThreadComposerRuntime
extends ComposerRuntime
implements ThreadComposerState
export type ThreadComposerRuntime = Omit<
ComposerRuntime,
"getState" | "getAttachmentByIndex"
> & {
readonly type: "thread";
getState(): ThreadComposerState;

/** @deprecated This feature is being removed in 0.6.0. Submit feedback if you need it. */
focus(): void;

/** @deprecated This feature is being removed in 0.6.0. Submit feedback if you need it. */
onFocus(callback: () => void): Unsubscribe;

getAttachmentByIndex(
idx: number,
): AttachmentRuntime & { source: "thread-composer" };
};

export class ThreadComposerRuntimeImpl
extends ComposerRuntimeImpl
implements ThreadComposerRuntime, ThreadComposerState
{
public get type() {
return "thread" as const;
Expand Down Expand Up @@ -325,17 +386,23 @@ export class ThreadComposerRuntime
// TODO replace with events
private _focusListeners = new Set<() => void>();

/**
* @deprecated This feature is being removed in 0.6.0. Submit feedback if you need it.
*/
public focus() {
this._focusListeners.forEach((callback) => callback());
}

/**
* @deprecated This feature is being removed in 0.6.0. Submit feedback if you need it.
*/
public onFocus(callback: () => void) {
this._focusListeners.add(callback);
return () => this._focusListeners.delete(callback);
}

public getAttachmentByIndex(idx: number) {
return new ThreadComposerAttachmentRuntime(
return new ThreadComposerAttachmentRuntimeImpl(
new ShallowMemoizeSubject({
getState: () => {
const attachments = this.getState().attachments;
Expand All @@ -355,9 +422,27 @@ export class ThreadComposerRuntime
}
}

export class EditComposerRuntime
extends ComposerRuntime
implements EditComposerState
export type EditComposerRuntime = Omit<
ComposerRuntime,
"getState" | "getAttachmentByIndex"
> & {
readonly type: "edit";
getState(): EditComposerState;
beginEdit(): void;

/**
* @deprecated Use `beginEdit()` instead. This will be removed in 0.6.0.
*/
edit(): void;

getAttachmentByIndex(
idx: number,
): AttachmentRuntime & { source: "edit-composer" };
};

export class EditComposerRuntimeImpl
extends ComposerRuntimeImpl
implements EditComposerRuntime, EditComposerState
{
public get type() {
return "edit" as const;
Expand Down Expand Up @@ -397,7 +482,7 @@ export class EditComposerRuntime
}

public getAttachmentByIndex(idx: number) {
return new EditComposerAttachmentRuntime(
return new EditComposerAttachmentRuntimeImpl(
new ShallowMemoizeSubject({
getState: () => {
const attachments = this.getState().attachments;
Expand Down
9 changes: 8 additions & 1 deletion packages/react/src/api/ContentPartRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import { ThreadRuntimeCoreBinding } from "./ThreadRuntime";
import { MessageStateBinding } from "./MessageRuntime";
import { SubscribableWithState } from "./subscribable/Subscribable";
import { Unsubscribe } from "../types";

export type ContentPartState = (
| ThreadUserContentPart
Expand All @@ -21,7 +22,13 @@ export type ContentPartState = (

type ContentPartSnapshotBinding = SubscribableWithState<ContentPartState>;

export class ContentPartRuntime {
export type ContentPartRuntime = {
getState(): ContentPartState;
addToolResult(result: any): void;
subscribe(callback: () => void): Unsubscribe;
};

export class ContentPartRuntimeImpl implements ContentPartRuntime {
constructor(
private contentBinding: ContentPartSnapshotBinding,
private messageApi: MessageStateBinding,
Expand Down
Loading

0 comments on commit 2b7c6fe

Please sign in to comment.