Skip to content

Commit

Permalink
feat: create*Event methods now return strings (#59)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: All `create*Event` methods now return a string instead
of an object with a `.toString()` method.

Before:

```js
esponse.write(createTextEvent("Hello, world!").toString());
```

Now:

```js
esponse.write(createTextEvent("Hello, world!"));
```
  • Loading branch information
gr2m authored Sep 5, 2024
1 parent 9533a1f commit 43a5e4e
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 361 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ export default handler(request, response) {
const textEvent = createTextEvent("Hello, world!");
const doneEvent = createDoneEvent();

response.write(ackEvent.toString());
response.write(textEvent.toString());
response.end(doneEvent.toString());
response.write(ackEvent);
response.write(textEvent);
response.end(doneEvent);
}
```

Expand Down Expand Up @@ -131,7 +131,7 @@ const payloadIsVerified = await verifyRequestPayload(

### Response

All `create*Event()` methods return an object with a `.toString()` method, which is called automatically when a string is expected. Unfortunately that's not the case for `response.write()`, you need to call `.toString()` explicitly.
All `create*Event()` methods return a string that can directly be written to the response stream.

#### `createAckEvent()`

Expand All @@ -141,7 +141,7 @@ The `ack` event should only be sent once.
```js
import { createAckEvent } from "@copilot-extensions/preview-sdk";

response.write(createAckEvent().toString());
response.write(createAckEvent());
```

#### `createTextEvent(message)`
Expand All @@ -151,8 +151,8 @@ Send a text message to the chat UI. Multiple messages can be sent. The `message`
```js
import { createTextEvent } from "@copilot-extensions/preview-sdk";

response.write(createTextEvent("Hello, world!").toString());
response.write(createTextEvent("Hello, again!").toString());
response.write(createTextEvent("Hello, world!"));
response.write(createTextEvent("Hello, again!"));
```

#### `createConfirmationEvent({ id, title, message, metadata })`
Expand All @@ -171,7 +171,7 @@ response.write(
id: "123",
title: "Are you sure?",
message: "This will do something.",
}).toString(),
}),
);
```

Expand Down Expand Up @@ -209,7 +209,7 @@ response.write(
display_icon: "issue-opened",
display_url: "https://github.com/monalisa/hello-world/issues/123",
},
]).toString()
])
);
```
Expand All @@ -231,7 +231,7 @@ The `done` event should only be sent once, at the end of the response. No furthe
```js
import { createDoneEvent } from "@copilot-extensions/preview-sdk";

response.write(createDoneEvent().toString());
response.write(createDoneEvent());
```
### Parsing
Expand Down
83 changes: 6 additions & 77 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@ interface VerifyRequestByKeyIdInterface {
// response types

export interface CreateAckEventInterface {
(): ResponseEvent<"ack">;
(): string;
}

export interface CreateTextEventInterface {
(message: string): ResponseEvent<"text">;
(message: string): string;
}

export type CreateConfirmationEventOptions = {
Expand All @@ -50,88 +49,18 @@ export type CreateConfirmationEventOptions = {
export interface CreateConfirmationEventInterface {
(
options: CreateConfirmationEventOptions,
): ResponseEvent<"copilot_confirmation">;
): string;
}
export interface CreateReferencesEventInterface {
(references: CopilotReference[]): ResponseEvent<"copilot_references">;
(references: CopilotReference[]): string;
}
export interface CreateErrorsEventInterface {
(errors: CopilotError[]): ResponseEvent<"copilot_errors">;
(errors: CopilotError[]): string;
}
export interface CreateDoneEventInterface {
(): ResponseEvent<"done">;
(): string;
}

type ResponseEventType =
| "ack"
| "done"
| "text"
| "copilot_references"
| "copilot_confirmation"
| "copilot_errors";
type EventsWithoutEventKey = "ack" | "done" | "text";
type ResponseEvent<T extends ResponseEventType = "text"> =
T extends EventsWithoutEventKey
? {
data: T extends "ack"
? CopilotAckResponseEventData
: T extends "done"
? CopilotDoneResponseEventData
: T extends "text"
? CopilotTextResponseEventData
: never;
toString: () => string;
}
: {
event: T;
data: T extends "copilot_references"
? CopilotReferenceResponseEventData
: T extends "copilot_confirmation"
? CopilotConfirmationResponseEventData
: T extends "copilot_errors"
? CopilotErrorsResponseEventData
: never;
toString: () => string;
};

type CopilotAckResponseEventData = {
choices: [
{
delta: InteropMessage<"assistant">;
},
];
};

type CopilotDoneResponseEventData = {
choices: [
{
finish_reason: "stop";
delta: {
content: null;
};
},
];
};

type CopilotTextResponseEventData = {
choices: [
{
delta: InteropMessage<"assistant">;
},
];
};
type CopilotConfirmationResponseEventData = {
type: "action";
title: string;
message: string;
confirmation?: {
id: string;
[key: string]: any;
};
};
type CopilotErrorsResponseEventData = CopilotError[];
type CopilotReferenceResponseEventData = CopilotReference[];

type CopilotError = {
type: "reference" | "function" | "agent";
code: string;
Expand Down
108 changes: 7 additions & 101 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,36 +87,12 @@ export async function fetchVerificationKeysTest() {

export function createAckEventTest() {
const event = createAckEvent();
expectType<() => string>(event.toString);
expectType<string>(event.toString());

expectType<{
choices: [
{
delta: InteropMessage<"assistant">;
},
];
}>(event.data);

// @ts-expect-error - .event is required
event.event;
expectType<string>(event);
}

export function createTextEventTest() {
const event = createTextEvent("test");
expectType<() => string>(event.toString);
expectType<string>(event.toString());

expectType<{
choices: [
{
delta: InteropMessage<"assistant">;
},
];
}>(event.data);

// @ts-expect-error - .event is required
event.event;
expectType<string>(event);
}

export function createConfirmationEventTest() {
Expand All @@ -125,31 +101,7 @@ export function createConfirmationEventTest() {
title: "test",
message: "test",
});

// optional metadata
createConfirmationEvent({
id: "test",
title: "test",
message: "test",
metadata: {
someOtherId: "test",
},
});

expectType<() => string>(event.toString);
expectType<string>(event.toString());

expectType<{
type: "action";
title: string;
message: string;
confirmation?: {
id: string;
[key: string]: any;
};
}>(event.data);

expectType<"copilot_confirmation">(event.event);
expectType<string>(event);
}

export function createReferencesEventTest() {
Expand All @@ -172,26 +124,7 @@ export function createReferencesEventTest() {
},
},
]);
expectType<() => string>(event.toString);
expectType<string>(event.toString());

expectType<
{
type: string;
id: string;
data?: {
[key: string]: unknown;
};
is_implicit?: boolean;
metadata?: {
display_name: string;
display_icon?: string;
display_url?: string;
};
}[]
>(event.data);

expectType<"copilot_references">(event.event);
expectType<string>(event);
}

export function createErrorsEventTest() {
Expand All @@ -215,39 +148,12 @@ export function createErrorsEventTest() {
identifier: "agent-identifier",
},
]);
expectType<() => string>(event.toString);
expectType<string>(event.toString());

expectType<
{
type: "reference" | "function" | "agent";
code: string;
message: string;
identifier: string;
}[]
>(event.data);

expectType<"copilot_errors">(event.event);
expectType<string>(event);
}

export function createDoneEventTest() {
const event = createDoneEvent();
expectType<() => string>(event.toString);
expectType<string>(event.toString());

expectType<{
choices: [
{
finish_reason: "stop";
delta: {
content: null;
};
},
];
}>(event.data);

// @ts-expect-error - .event is required
event.event;
expectType<string>(event);
}

export function parseRequestBodyTest(body: string) {
Expand Down Expand Up @@ -312,7 +218,7 @@ export async function promptTest() {
await prompt("What is the capital of France?", {
token: "secret",
request: {
fetch: () => {},
fetch: () => { },
},
});

Expand Down
Loading

0 comments on commit 43a5e4e

Please sign in to comment.