chore: move acp to sdk (#8556)

This commit is contained in:
Alex Hancock
2026-04-15 13:00:12 -04:00
committed by GitHub
parent 78b5b5209a
commit a7396a7bd0
17 changed files with 14 additions and 14 deletions
+178
View File
@@ -0,0 +1,178 @@
// This file is auto-generated — do not edit manually.
export interface ExtMethodProvider {
extMethod(
method: string,
params: Record<string, unknown>,
): Promise<Record<string, unknown>>;
}
import type {
AddExtensionRequest,
ArchiveSessionRequest,
CheckSecretRequest,
CheckSecretResponse,
DeleteSessionRequest,
ExportSessionRequest,
ExportSessionResponse,
GetExtensionsRequest,
GetExtensionsResponse,
GetProviderDetailsRequest,
GetProviderDetailsResponse,
GetProviderModelsRequest,
GetProviderModelsResponse,
GetToolsRequest,
GetToolsResponse,
ImportSessionRequest,
ImportSessionResponse,
ListProvidersRequest,
ListProvidersResponse,
ReadConfigRequest,
ReadConfigResponse,
ReadResourceRequest,
ReadResourceResponse,
RemoveConfigRequest,
RemoveExtensionRequest,
RemoveSecretRequest,
UnarchiveSessionRequest,
UpdateProviderRequest,
UpdateProviderResponse,
UpdateWorkingDirRequest,
UpsertConfigRequest,
UpsertSecretRequest,
} from './types.gen.js';
import {
zCheckSecretResponse,
zExportSessionResponse,
zGetExtensionsResponse,
zGetProviderDetailsResponse,
zGetProviderModelsResponse,
zGetToolsResponse,
zImportSessionResponse,
zListProvidersResponse,
zReadConfigResponse,
zReadResourceResponse,
zUpdateProviderResponse,
} from './zod.gen.js';
export class GooseExtClient {
constructor(private conn: ExtMethodProvider) {}
async GooseExtensionsAdd(params: AddExtensionRequest): Promise<void> {
await this.conn.extMethod("_goose/extensions/add", params);
}
async GooseExtensionsRemove(params: RemoveExtensionRequest): Promise<void> {
await this.conn.extMethod("_goose/extensions/remove", params);
}
async GooseTools(params: GetToolsRequest): Promise<GetToolsResponse> {
const raw = await this.conn.extMethod("_goose/tools", params);
return zGetToolsResponse.parse(raw) as GetToolsResponse;
}
async GooseResourceRead(
params: ReadResourceRequest,
): Promise<ReadResourceResponse> {
const raw = await this.conn.extMethod("_goose/resource/read", params);
return zReadResourceResponse.parse(raw) as ReadResourceResponse;
}
async GooseWorkingDirUpdate(params: UpdateWorkingDirRequest): Promise<void> {
await this.conn.extMethod("_goose/working_dir/update", params);
}
async sessionDelete(params: DeleteSessionRequest): Promise<void> {
await this.conn.extMethod("session/delete", params);
}
async GooseConfigExtensions(
params: GetExtensionsRequest,
): Promise<GetExtensionsResponse> {
const raw = await this.conn.extMethod("_goose/config/extensions", params);
return zGetExtensionsResponse.parse(raw) as GetExtensionsResponse;
}
async GooseSessionProviderUpdate(
params: UpdateProviderRequest,
): Promise<UpdateProviderResponse> {
const raw = await this.conn.extMethod(
"_goose/session/provider/update",
params,
);
return zUpdateProviderResponse.parse(raw) as UpdateProviderResponse;
}
async GooseProvidersList(
params: ListProvidersRequest,
): Promise<ListProvidersResponse> {
const raw = await this.conn.extMethod("_goose/providers/list", params);
return zListProvidersResponse.parse(raw) as ListProvidersResponse;
}
async GooseProvidersDetails(
params: GetProviderDetailsRequest,
): Promise<GetProviderDetailsResponse> {
const raw = await this.conn.extMethod("_goose/providers/details", params);
return zGetProviderDetailsResponse.parse(raw) as GetProviderDetailsResponse;
}
async GooseProvidersModels(
params: GetProviderModelsRequest,
): Promise<GetProviderModelsResponse> {
const raw = await this.conn.extMethod("_goose/providers/models", params);
return zGetProviderModelsResponse.parse(raw) as GetProviderModelsResponse;
}
async GooseConfigRead(
params: ReadConfigRequest,
): Promise<ReadConfigResponse> {
const raw = await this.conn.extMethod("_goose/config/read", params);
return zReadConfigResponse.parse(raw) as ReadConfigResponse;
}
async GooseConfigUpsert(params: UpsertConfigRequest): Promise<void> {
await this.conn.extMethod("_goose/config/upsert", params);
}
async GooseConfigRemove(params: RemoveConfigRequest): Promise<void> {
await this.conn.extMethod("_goose/config/remove", params);
}
async GooseSecretCheck(
params: CheckSecretRequest,
): Promise<CheckSecretResponse> {
const raw = await this.conn.extMethod("_goose/secret/check", params);
return zCheckSecretResponse.parse(raw) as CheckSecretResponse;
}
async GooseSecretUpsert(params: UpsertSecretRequest): Promise<void> {
await this.conn.extMethod("_goose/secret/upsert", params);
}
async GooseSecretRemove(params: RemoveSecretRequest): Promise<void> {
await this.conn.extMethod("_goose/secret/remove", params);
}
async GooseSessionExport(
params: ExportSessionRequest,
): Promise<ExportSessionResponse> {
const raw = await this.conn.extMethod("_goose/session/export", params);
return zExportSessionResponse.parse(raw) as ExportSessionResponse;
}
async GooseSessionImport(
params: ImportSessionRequest,
): Promise<ImportSessionResponse> {
const raw = await this.conn.extMethod("_goose/session/import", params);
return zImportSessionResponse.parse(raw) as ImportSessionResponse;
}
async GooseSessionArchive(params: ArchiveSessionRequest): Promise<void> {
await this.conn.extMethod("_goose/session/archive", params);
}
async GooseSessionUnarchive(params: UnarchiveSessionRequest): Promise<void> {
await this.conn.extMethod("_goose/session/unarchive", params);
}
}
+113
View File
@@ -0,0 +1,113 @@
// This file is auto-generated by @hey-api/openapi-ts
export type { AddExtensionRequest, ArchiveSessionRequest, CheckSecretRequest, CheckSecretResponse, DeleteSessionRequest, EmptyResponse, ExportSessionRequest, ExportSessionResponse, ExtRequest, ExtResponse, GetExtensionsRequest, GetExtensionsResponse, GetProviderDetailsRequest, GetProviderDetailsResponse, GetProviderModelsRequest, GetProviderModelsResponse, GetToolsRequest, GetToolsResponse, ImportSessionRequest, ImportSessionResponse, ListProvidersRequest, ListProvidersResponse, ModelEntry, ProviderConfigKey, ProviderDetailEntry, ProviderListEntry, ReadConfigRequest, ReadConfigResponse, ReadResourceRequest, ReadResourceResponse, RemoveConfigRequest, RemoveExtensionRequest, RemoveSecretRequest, UnarchiveSessionRequest, UpdateProviderRequest, UpdateProviderResponse, UpdateWorkingDirRequest, UpsertConfigRequest, UpsertSecretRequest } from './types.gen.js';
export const GOOSE_EXT_METHODS = [
{
method: "_goose/extensions/add",
requestType: "AddExtensionRequest",
responseType: "EmptyResponse",
},
{
method: "_goose/extensions/remove",
requestType: "RemoveExtensionRequest",
responseType: "EmptyResponse",
},
{
method: "_goose/tools",
requestType: "GetToolsRequest",
responseType: "GetToolsResponse",
},
{
method: "_goose/resource/read",
requestType: "ReadResourceRequest",
responseType: "ReadResourceResponse",
},
{
method: "_goose/working_dir/update",
requestType: "UpdateWorkingDirRequest",
responseType: "EmptyResponse",
},
{
method: "session/delete",
requestType: "DeleteSessionRequest",
responseType: "EmptyResponse",
},
{
method: "_goose/config/extensions",
requestType: "GetExtensionsRequest",
responseType: "GetExtensionsResponse",
},
{
method: "_goose/session/provider/update",
requestType: "UpdateProviderRequest",
responseType: "UpdateProviderResponse",
},
{
method: "_goose/providers/list",
requestType: "ListProvidersRequest",
responseType: "ListProvidersResponse",
},
{
method: "_goose/providers/details",
requestType: "GetProviderDetailsRequest",
responseType: "GetProviderDetailsResponse",
},
{
method: "_goose/providers/models",
requestType: "GetProviderModelsRequest",
responseType: "GetProviderModelsResponse",
},
{
method: "_goose/config/read",
requestType: "ReadConfigRequest",
responseType: "ReadConfigResponse",
},
{
method: "_goose/config/upsert",
requestType: "UpsertConfigRequest",
responseType: "EmptyResponse",
},
{
method: "_goose/config/remove",
requestType: "RemoveConfigRequest",
responseType: "EmptyResponse",
},
{
method: "_goose/secret/check",
requestType: "CheckSecretRequest",
responseType: "CheckSecretResponse",
},
{
method: "_goose/secret/upsert",
requestType: "UpsertSecretRequest",
responseType: "EmptyResponse",
},
{
method: "_goose/secret/remove",
requestType: "RemoveSecretRequest",
responseType: "EmptyResponse",
},
{
method: "_goose/session/export",
requestType: "ExportSessionRequest",
responseType: "ExportSessionResponse",
},
{
method: "_goose/session/import",
requestType: "ImportSessionRequest",
responseType: "ImportSessionResponse",
},
{
method: "_goose/session/archive",
requestType: "ArchiveSessionRequest",
responseType: "EmptyResponse",
},
{
method: "_goose/session/unarchive",
requestType: "UnarchiveSessionRequest",
responseType: "EmptyResponse",
},
] as const;
export type GooseExtMethod = (typeof GOOSE_EXT_METHODS)[number];
+317
View File
@@ -0,0 +1,317 @@
// This file is auto-generated by @hey-api/openapi-ts
/**
* Add an extension to an active session.
*/
export type AddExtensionRequest = {
sessionId: string;
/**
* Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform).
*/
config?: unknown;
};
/**
* Empty success response for operations that return no data.
*/
export type EmptyResponse = {
[key: string]: unknown;
};
/**
* Remove an extension from an active session.
*/
export type RemoveExtensionRequest = {
sessionId: string;
name: string;
};
/**
* List all tools available in a session.
*/
export type GetToolsRequest = {
sessionId: string;
};
/**
* Tools response.
*/
export type GetToolsResponse = {
/**
* Array of tool info objects with `name`, `description`, `parameters`, and optional `permission`.
*/
tools: Array<unknown>;
};
/**
* Read a resource from an extension.
*/
export type ReadResourceRequest = {
sessionId: string;
uri: string;
extensionName: string;
};
/**
* Resource read response.
*/
export type ReadResourceResponse = {
/**
* The resource result from the extension (MCP ReadResourceResult).
*/
result?: unknown;
};
/**
* Update the working directory for a session.
*/
export type UpdateWorkingDirRequest = {
sessionId: string;
workingDir: string;
};
/**
* Delete a session.
*/
export type DeleteSessionRequest = {
sessionId: string;
};
/**
* List configured extensions and any warnings.
*/
export type GetExtensionsRequest = {
[key: string]: unknown;
};
/**
* List configured extensions and any warnings.
*/
export type GetExtensionsResponse = {
/**
* Array of ExtensionEntry objects with `enabled` flag and config details.
*/
extensions: Array<unknown>;
warnings: Array<string>;
};
/**
* Atomically update the provider for a live session.
*/
export type UpdateProviderRequest = {
sessionId: string;
provider: string;
model?: string | null;
contextLimit?: number | null;
requestParams?: {
[key: string]: unknown;
} | null;
};
/**
* Provider update response.
*/
export type UpdateProviderResponse = {
/**
* Refreshed session config options after the provider/model change.
*/
configOptions: Array<unknown>;
};
/**
* List providers available through goose, including the config-default sentinel.
*/
export type ListProvidersRequest = {
[key: string]: unknown;
};
/**
* Provider list response.
*/
export type ListProvidersResponse = {
providers: Array<ProviderListEntry>;
};
export type ProviderListEntry = {
id: string;
label: string;
};
/**
* List providers with full metadata (config keys, setup steps, etc.).
*/
export type GetProviderDetailsRequest = {
[key: string]: unknown;
};
/**
* Provider details response.
*/
export type GetProviderDetailsResponse = {
providers: Array<ProviderDetailEntry>;
};
export type ProviderDetailEntry = {
name: string;
displayName: string;
description: string;
defaultModel: string;
isConfigured: boolean;
providerType: string;
configKeys: Array<ProviderConfigKey>;
setupSteps?: Array<string>;
knownModels?: Array<ModelEntry>;
};
export type ProviderConfigKey = {
name: string;
required: boolean;
secret: boolean;
default?: string | null;
oauthFlow?: boolean;
deviceCodeFlow?: boolean;
primary?: boolean;
};
export type ModelEntry = {
name: string;
contextLimit: number;
};
/**
* Fetch the full list of models available for a specific provider.
*/
export type GetProviderModelsRequest = {
providerName: string;
};
/**
* Provider models response.
*/
export type GetProviderModelsResponse = {
models: Array<string>;
};
/**
* Read a single non-secret config value.
*/
export type ReadConfigRequest = {
key: string;
};
/**
* Config read response.
*/
export type ReadConfigResponse = {
value?: unknown;
};
/**
* Upsert a single non-secret config value.
*/
export type UpsertConfigRequest = {
key: string;
value: unknown;
};
/**
* Remove a single non-secret config value.
*/
export type RemoveConfigRequest = {
key: string;
};
/**
* Check whether a secret exists. Never returns the actual value.
*/
export type CheckSecretRequest = {
key: string;
};
/**
* Secret check response.
*/
export type CheckSecretResponse = {
exists: boolean;
};
/**
* Set a secret value (write-only).
*/
export type UpsertSecretRequest = {
key: string;
value: unknown;
};
/**
* Remove a secret.
*/
export type RemoveSecretRequest = {
key: string;
};
/**
* Export a session as a JSON string.
*/
export type ExportSessionRequest = {
sessionId: string;
};
/**
* Export session response — raw JSON of the goose session with `conversation`.
*/
export type ExportSessionResponse = {
data: string;
};
/**
* Import a session from a JSON string.
*/
export type ImportSessionRequest = {
data: string;
};
/**
* Import session response — metadata about the newly created session.
*/
export type ImportSessionResponse = {
sessionId: string;
title?: string | null;
updatedAt?: string | null;
messageCount: number;
};
/**
* Archive a session (soft delete).
*/
export type ArchiveSessionRequest = {
sessionId: string;
};
/**
* Unarchive a previously archived session.
*/
export type UnarchiveSessionRequest = {
sessionId: string;
};
export type ExtRequest = {
id: string;
method: string;
params?: AddExtensionRequest | RemoveExtensionRequest | GetToolsRequest | ReadResourceRequest | UpdateWorkingDirRequest | DeleteSessionRequest | GetExtensionsRequest | UpdateProviderRequest | ListProvidersRequest | GetProviderDetailsRequest | GetProviderModelsRequest | ReadConfigRequest | UpsertConfigRequest | RemoveConfigRequest | CheckSecretRequest | UpsertSecretRequest | RemoveSecretRequest | ExportSessionRequest | ImportSessionRequest | ArchiveSessionRequest | UnarchiveSessionRequest | {
[key: string]: unknown;
} | null;
};
export type ExtResponse = {
id: string;
result?: EmptyResponse | GetToolsResponse | ReadResourceResponse | GetExtensionsResponse | UpdateProviderResponse | ListProvidersResponse | GetProviderDetailsResponse | GetProviderModelsResponse | ReadConfigResponse | CheckSecretResponse | ExportSessionResponse | ImportSessionResponse | unknown;
} | {
error: {
code: number;
message: string;
data?: unknown;
};
id: string;
};
+356
View File
@@ -0,0 +1,356 @@
// This file is auto-generated by @hey-api/openapi-ts
import { z } from 'zod';
/**
* Add an extension to an active session.
*/
export const zAddExtensionRequest = z.object({
sessionId: z.string(),
config: z.unknown().optional().default(null)
});
/**
* Empty success response for operations that return no data.
*/
export const zEmptyResponse = z.record(z.unknown());
/**
* Remove an extension from an active session.
*/
export const zRemoveExtensionRequest = z.object({
sessionId: z.string(),
name: z.string()
});
/**
* List all tools available in a session.
*/
export const zGetToolsRequest = z.object({
sessionId: z.string()
});
/**
* Tools response.
*/
export const zGetToolsResponse = z.object({
tools: z.array(z.unknown())
});
/**
* Read a resource from an extension.
*/
export const zReadResourceRequest = z.object({
sessionId: z.string(),
uri: z.string(),
extensionName: z.string()
});
/**
* Resource read response.
*/
export const zReadResourceResponse = z.object({
result: z.unknown().optional().default(null)
});
/**
* Update the working directory for a session.
*/
export const zUpdateWorkingDirRequest = z.object({
sessionId: z.string(),
workingDir: z.string()
});
/**
* Delete a session.
*/
export const zDeleteSessionRequest = z.object({
sessionId: z.string()
});
/**
* List configured extensions and any warnings.
*/
export const zGetExtensionsRequest = z.record(z.unknown());
/**
* List configured extensions and any warnings.
*/
export const zGetExtensionsResponse = z.object({
extensions: z.array(z.unknown()),
warnings: z.array(z.string())
});
/**
* Atomically update the provider for a live session.
*/
export const zUpdateProviderRequest = z.object({
sessionId: z.string(),
provider: z.string(),
model: z.union([
z.string(),
z.null()
]).optional(),
contextLimit: z.union([
z.number().int().gte(0),
z.null()
]).optional(),
requestParams: z.union([
z.record(z.unknown()),
z.null()
]).optional()
});
/**
* Provider update response.
*/
export const zUpdateProviderResponse = z.object({
configOptions: z.array(z.unknown())
});
/**
* List providers available through goose, including the config-default sentinel.
*/
export const zListProvidersRequest = z.record(z.unknown());
export const zProviderListEntry = z.object({
id: z.string(),
label: z.string()
});
/**
* Provider list response.
*/
export const zListProvidersResponse = z.object({
providers: z.array(zProviderListEntry)
});
/**
* List providers with full metadata (config keys, setup steps, etc.).
*/
export const zGetProviderDetailsRequest = z.record(z.unknown());
export const zProviderConfigKey = z.object({
name: z.string(),
required: z.boolean(),
secret: z.boolean(),
default: z.union([
z.string(),
z.null()
]).optional().default(null),
oauthFlow: z.boolean().optional().default(false),
deviceCodeFlow: z.boolean().optional().default(false),
primary: z.boolean().optional().default(false)
});
export const zModelEntry = z.object({
name: z.string(),
contextLimit: z.number().int().gte(0)
});
export const zProviderDetailEntry = z.object({
name: z.string(),
displayName: z.string(),
description: z.string(),
defaultModel: z.string(),
isConfigured: z.boolean(),
providerType: z.string(),
configKeys: z.array(zProviderConfigKey),
setupSteps: z.array(z.string()).optional().default([]),
knownModels: z.array(zModelEntry).optional().default([])
});
/**
* Provider details response.
*/
export const zGetProviderDetailsResponse = z.object({
providers: z.array(zProviderDetailEntry)
});
/**
* Fetch the full list of models available for a specific provider.
*/
export const zGetProviderModelsRequest = z.object({
providerName: z.string()
});
/**
* Provider models response.
*/
export const zGetProviderModelsResponse = z.object({
models: z.array(z.string())
});
/**
* Read a single non-secret config value.
*/
export const zReadConfigRequest = z.object({
key: z.string()
});
/**
* Config read response.
*/
export const zReadConfigResponse = z.object({
value: z.unknown().optional().default(null)
});
/**
* Upsert a single non-secret config value.
*/
export const zUpsertConfigRequest = z.object({
key: z.string(),
value: z.unknown()
});
/**
* Remove a single non-secret config value.
*/
export const zRemoveConfigRequest = z.object({
key: z.string()
});
/**
* Check whether a secret exists. Never returns the actual value.
*/
export const zCheckSecretRequest = z.object({
key: z.string()
});
/**
* Secret check response.
*/
export const zCheckSecretResponse = z.object({
exists: z.boolean()
});
/**
* Set a secret value (write-only).
*/
export const zUpsertSecretRequest = z.object({
key: z.string(),
value: z.unknown()
});
/**
* Remove a secret.
*/
export const zRemoveSecretRequest = z.object({
key: z.string()
});
/**
* Export a session as a JSON string.
*/
export const zExportSessionRequest = z.object({
sessionId: z.string()
});
/**
* Export session response — raw JSON of the goose session with `conversation`.
*/
export const zExportSessionResponse = z.object({
data: z.string()
});
/**
* Import a session from a JSON string.
*/
export const zImportSessionRequest = z.object({
data: z.string()
});
/**
* Import session response — metadata about the newly created session.
*/
export const zImportSessionResponse = z.object({
sessionId: z.string(),
title: z.union([
z.string(),
z.null()
]).optional(),
updatedAt: z.union([
z.string(),
z.null()
]).optional(),
messageCount: z.number().int().gte(0)
});
/**
* Archive a session (soft delete).
*/
export const zArchiveSessionRequest = z.object({
sessionId: z.string()
});
/**
* Unarchive a previously archived session.
*/
export const zUnarchiveSessionRequest = z.object({
sessionId: z.string()
});
export const zExtRequest = z.object({
id: z.string(),
method: z.string(),
params: z.union([
z.union([
zAddExtensionRequest,
zRemoveExtensionRequest,
zGetToolsRequest,
zReadResourceRequest,
zUpdateWorkingDirRequest,
zDeleteSessionRequest,
zGetExtensionsRequest,
zUpdateProviderRequest,
zListProvidersRequest,
zGetProviderDetailsRequest,
zGetProviderModelsRequest,
zReadConfigRequest,
zUpsertConfigRequest,
zRemoveConfigRequest,
zCheckSecretRequest,
zUpsertSecretRequest,
zRemoveSecretRequest,
zExportSessionRequest,
zImportSessionRequest,
zArchiveSessionRequest,
zUnarchiveSessionRequest
]),
z.union([
z.record(z.unknown()),
z.null()
])
]).optional()
});
export const zExtResponse = z.union([
z.object({
id: z.string(),
result: z.union([
z.union([
zEmptyResponse,
zGetToolsResponse,
zReadResourceResponse,
zGetExtensionsResponse,
zUpdateProviderResponse,
zListProvidersResponse,
zGetProviderDetailsResponse,
zGetProviderModelsResponse,
zReadConfigResponse,
zCheckSecretResponse,
zExportSessionResponse,
zImportSessionResponse
]),
z.unknown()
]).optional()
}),
z.object({
error: z.object({
code: z.number().int(),
message: z.string(),
data: z.unknown().optional()
}),
id: z.string()
})
]);
+123
View File
@@ -0,0 +1,123 @@
import {
ClientSideConnection,
type Client,
type Stream,
type InitializeRequest,
type InitializeResponse,
type NewSessionRequest,
type NewSessionResponse,
type LoadSessionRequest,
type LoadSessionResponse,
type PromptRequest,
type PromptResponse,
type CancelNotification,
type AuthenticateRequest,
type AuthenticateResponse,
type SetSessionModeRequest,
type SetSessionModeResponse,
type SetSessionConfigOptionRequest,
type SetSessionConfigOptionResponse,
type ForkSessionRequest,
type ForkSessionResponse,
type ListSessionsRequest,
type ListSessionsResponse,
type ResumeSessionRequest,
type ResumeSessionResponse,
type SetSessionModelRequest,
type SetSessionModelResponse,
} from "@agentclientprotocol/sdk";
import { GooseExtClient } from "./generated/client.gen.js";
import { createHttpStream } from "./http-stream.js";
export class GooseClient {
private conn: ClientSideConnection;
private ext: GooseExtClient;
constructor(toClient: () => Client, streamOrUrl: Stream | string) {
const stream =
typeof streamOrUrl === "string"
? createHttpStream(streamOrUrl)
: streamOrUrl;
this.conn = new ClientSideConnection(toClient, stream);
this.ext = new GooseExtClient(this.conn);
}
get signal(): AbortSignal {
return this.conn.signal;
}
get closed(): Promise<void> {
return this.conn.closed;
}
initialize(params: InitializeRequest): Promise<InitializeResponse> {
return this.conn.initialize(params);
}
newSession(params: NewSessionRequest): Promise<NewSessionResponse> {
return this.conn.newSession(params);
}
loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {
return this.conn.loadSession(params);
}
prompt(params: PromptRequest): Promise<PromptResponse> {
return this.conn.prompt(params);
}
cancel(params: CancelNotification): Promise<void> {
return this.conn.cancel(params);
}
authenticate(params: AuthenticateRequest): Promise<AuthenticateResponse> {
return this.conn.authenticate(params);
}
setSessionMode(
params: SetSessionModeRequest,
): Promise<SetSessionModeResponse> {
return this.conn.setSessionMode(params);
}
setSessionConfigOption(
params: SetSessionConfigOptionRequest,
): Promise<SetSessionConfigOptionResponse> {
return this.conn.setSessionConfigOption(params);
}
unstable_forkSession(
params: ForkSessionRequest,
): Promise<ForkSessionResponse> {
return this.conn.unstable_forkSession(params);
}
unstable_listSessions(
params: ListSessionsRequest,
): Promise<ListSessionsResponse> {
return this.conn.unstable_listSessions(params);
}
unstable_resumeSession(
params: ResumeSessionRequest,
): Promise<ResumeSessionResponse> {
return this.conn.unstable_resumeSession(params);
}
unstable_setSessionModel(
params: SetSessionModelRequest,
): Promise<SetSessionModelResponse> {
return this.conn.unstable_setSessionModel(params);
}
extMethod(
method: string,
params: Record<string, unknown>,
): Promise<Record<string, unknown>> {
return this.conn.extMethod(method, params);
}
get goose(): GooseExtClient {
return this.ext;
}
}
+120
View File
@@ -0,0 +1,120 @@
import type { AnyMessage, Stream } from "@agentclientprotocol/sdk";
const ACP_SESSION_HEADER = "Acp-Session-Id";
export function createHttpStream(serverUrl: string): Stream {
let sessionId: string | null = null;
const incoming: AnyMessage[] = [];
const waiters: Array<() => void> = [];
const sseAbort = new AbortController();
function pushMessage(msg: AnyMessage) {
incoming.push(msg);
const w = waiters.shift();
if (w) w();
}
function waitForMessage(): Promise<void> {
if (incoming.length > 0) return Promise.resolve();
return new Promise<void>((r) => waiters.push(r));
}
async function consumeSSE(response: Response) {
if (!response.body) return;
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const parts = buffer.split("\n\n");
buffer = parts.pop() || "";
for (const part of parts) {
for (const line of part.split("\n")) {
if (line.startsWith("data: ")) {
try {
const msg = JSON.parse(line.slice(6)) as AnyMessage;
pushMessage(msg);
} catch {
// ignore malformed JSON
}
}
}
}
}
} catch (e: unknown) {
if (e instanceof DOMException && e.name === "AbortError") return;
}
}
let isFirstRequest = true;
const readable = new ReadableStream<AnyMessage>({
async pull(controller) {
await waitForMessage();
while (incoming.length > 0) {
controller.enqueue(incoming.shift()!);
}
},
});
const writable = new WritableStream<AnyMessage>({
async write(msg) {
const isRequest =
"method" in msg &&
"id" in msg &&
msg.id !== undefined &&
msg.id !== null;
const headers: Record<string, string> = {
"Content-Type": "application/json",
Accept: "application/json, text/event-stream",
};
if (sessionId) {
headers[ACP_SESSION_HEADER] = sessionId;
}
if (isFirstRequest && isRequest) {
isFirstRequest = false;
const response = await fetch(`${serverUrl}/acp`, {
method: "POST",
headers,
body: JSON.stringify(msg),
signal: sseAbort.signal,
});
const sid = response.headers.get(ACP_SESSION_HEADER);
if (sid) sessionId = sid;
consumeSSE(response);
} else if (isRequest) {
const abort = new AbortController();
fetch(`${serverUrl}/acp`, {
method: "POST",
headers,
body: JSON.stringify(msg),
signal: abort.signal,
}).catch(() => {});
setTimeout(() => abort.abort(), 200);
} else {
await fetch(`${serverUrl}/acp`, {
method: "POST",
headers,
body: JSON.stringify(msg),
});
}
},
close() {
sseAbort.abort();
},
});
return { readable, writable };
}
+10
View File
@@ -0,0 +1,10 @@
export * from "./generated/types.gen.js";
export * from "./generated/zod.gen.js";
export { GooseClient } from "./goose-client.js";
export { createHttpStream } from "./http-stream.js";
export {
ClientSideConnection,
type Client,
type Stream,
} from "@agentclientprotocol/sdk";