import { ACPAgent, type ACPAgentProps, type ACPAgentSourceFile } from '../acp-agent'; import { detachedManifestScope, defineComponent, sourceEntry, validateCustomApiName } from './component'; import type { RipplingSDK } from '../../../client'; import type { RequestOptions } from '../../../internal/request-options'; import type { SessionCreateParams, SessionListParams, SessionCreateResponse, SessionListResponse, SessionListResponsesPageCursorURL, } from '../../../resources/agents/sessions/sessions'; import type { AgentRetrieveResponse } from '../../../resources/agents/agents'; import type { APIPromise } from '../../../core/api-promise'; import type { PagePromise } from '../../../core/pagination'; export type DefinedAgentProps = { apiName: `${string}__c` } & ( | (ACPAgentProps & { source?: never }) | (Omit & { source: URL; files?: never; entrypoint?: never }) ); /** Authenticated agent resources supplied per call. */ export interface AgentOperationsContext { readonly agents: { readonly retrieve: RipplingSDK['agents']['retrieve']; readonly sessions: Pick; }; } export interface AgentSessions { create( ctx: AgentOperationsContext, params: Omit, options?: RequestOptions, ): APIPromise; list( ctx: AgentOperationsContext, params?: SessionListParams, options?: RequestOptions, ): PagePromise; } export interface AgentOperations { retrieve(ctx: AgentOperationsContext, options?: RequestOptions): APIPromise; sessions: AgentSessions; } export interface AgentClient { retrieve(options?: RequestOptions): APIPromise; sessions: { create( params: Omit, options?: RequestOptions, ): APIPromise; list( params?: SessionListParams, options?: RequestOptions, ): PagePromise; }; } export function defineAgent(props: DefinedAgentProps): DefinedAgent { if (props.source !== undefined && (props.files !== undefined || props.entrypoint !== undefined)) throw new Error('Define an agent with either source or files/entrypoint, not both.'); return agentComponent.register(new DefinedAgent(props), props); } export class DefinedAgent extends ACPAgent { private _source: URL | undefined; readonly retrieve: ( ctx: AgentOperationsContext, options?: RequestOptions, ) => APIPromise; readonly sessions: AgentSessions; constructor(props: DefinedAgentProps) { validateCustomApiName(props.apiName); if (props.source !== undefined && props.source.protocol !== 'file:') throw new Error('Component source must be a file URL.'); super( detachedManifestScope, props.source !== undefined ? { ...props, files: [], entrypoint: 'index.ts' } : (props as ACPAgentProps), ); this._source = props.source === undefined ? undefined : new URL(props.source.href); const operations = createAgentOperations(this); this.retrieve = operations.retrieve; this.sessions = operations.sessions; } get source(): URL | undefined { return this._source; } /** Replaces inline files or a file-backed source with the supplied files and entrypoint. */ override setSource(files: ACPAgentSourceFile[], entrypoint: string): this { super.setSource(files, entrypoint); this._source = undefined; return this; } } interface AgentMetadata { type: 'ACP_AGENT'; api_name: string; source_agent_id: string; name: string; entrypoint: string; files: { type: 'ACP_AGENT'; path: string; content: string; kind: string }[]; } /** @internal Shared with the legacy client helper, including constructor-based agent references. */ function createAgentOperations(definition: ACPAgent): AgentOperations { return { retrieve: (ctx: AgentOperationsContext, options?: RequestOptions) => ctx.agents.retrieve(definition.getApiName(), options), sessions: { create: ( ctx: AgentOperationsContext, params: Omit, options?: RequestOptions, ) => ctx.agents.sessions.create({ ...params, agent_id: definition.getApiName() }, options), list: (ctx: AgentOperationsContext, params?: SessionListParams, options?: RequestOptions) => ctx.agents.sessions.list(definition.getApiName(), params, options), }, }; } const agentComponent = defineComponent({ type: 'ACP_AGENT', define: defineAgent, serialize: (definition) => sourceEntry(definition.toDict() as AgentMetadata, definition.source, (config, content) => ({ ...config, files: [{ type: 'ACP_AGENT' as const, path: 'index.ts', content, kind: 'typescript' }], entrypoint: 'index.ts', })), }); /** @internal Forward client helpers to the definition operations. */ export function createAgentClient(ctx: AgentOperationsContext, definition: ACPAgent): AgentClient { const operations = createAgentOperations(definition); return { retrieve: (options?: RequestOptions) => operations.retrieve(ctx, options), sessions: { create: (params: Omit, options?: RequestOptions) => operations.sessions.create(ctx, params, options), list: (params?: SessionListParams, options?: RequestOptions) => operations.sessions.list(ctx, params, options), }, }; }