@realtimex/sdk 1.3.6 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -41,6 +41,7 @@ interface TriggerAgentResponse {
41
41
  success: boolean;
42
42
  task_uuid?: string;
43
43
  task_id?: string;
44
+ capability_id?: string;
44
45
  event_id?: string;
45
46
  attempt_id?: string;
46
47
  event_type?: ContractEventType | string;
@@ -59,21 +60,72 @@ interface ContractCallbackMetadata {
59
60
  attempt_id_format?: string;
60
61
  idempotency?: string;
61
62
  }
63
+ interface ContractCapabilityTrigger$1 {
64
+ event: string;
65
+ route?: string;
66
+ payload_template?: Record<string, unknown>;
67
+ }
68
+ interface ContractCapability$1 {
69
+ capability_id: string;
70
+ name: string;
71
+ description?: string;
72
+ input_schema: Record<string, unknown>;
73
+ output_schema?: Record<string, unknown>;
74
+ permission?: string;
75
+ trigger?: ContractCapabilityTrigger$1;
76
+ tags?: string[];
77
+ examples?: string[];
78
+ risk_level?: 'low' | 'medium' | 'high' | null;
79
+ enabled?: boolean;
80
+ }
62
81
  interface LocalAppContractDefinition {
63
82
  id: string;
64
83
  version: string;
84
+ strictness?: 'compatible' | 'strict';
65
85
  events: Record<string, ContractEventType>;
66
86
  supported_events: ContractEventType[];
67
87
  supported_legacy_events: string[];
68
88
  aliases: Record<string, ContractEventType>;
69
89
  status_map: Record<string, string>;
70
90
  legacy_action_map: Record<ContractEventType, string>;
91
+ catalog_hash?: string;
92
+ capability_count?: number;
93
+ capabilities?: ContractCapability$1[];
71
94
  callback?: ContractCallbackMetadata;
72
95
  }
73
96
  interface LocalAppContractResponse {
74
97
  success: boolean;
75
98
  contract: LocalAppContractDefinition;
76
99
  }
100
+ interface LocalAppCapabilitiesResponse {
101
+ success: boolean;
102
+ contract_version: string;
103
+ strictness?: 'compatible' | 'strict';
104
+ catalog_hash?: string;
105
+ count: number;
106
+ capabilities: ContractCapability$1[];
107
+ }
108
+ interface LocalAppCapabilitySearchResponse extends LocalAppCapabilitiesResponse {
109
+ query: string;
110
+ }
111
+ interface LocalAppCapabilityDetailResponse {
112
+ success: boolean;
113
+ contract_version: string;
114
+ strictness?: 'compatible' | 'strict';
115
+ catalog_hash?: string;
116
+ capability: ContractCapability$1;
117
+ }
118
+ interface ContractInvokePayload {
119
+ capability_id: string;
120
+ args?: Record<string, unknown>;
121
+ auto_run?: boolean;
122
+ agent_name?: string;
123
+ workspace_slug?: string;
124
+ thread_slug?: string;
125
+ prompt?: string;
126
+ event_id?: string;
127
+ attempt_id?: string | number;
128
+ }
77
129
  interface Agent {
78
130
  slug: string;
79
131
  name: string;
@@ -1065,6 +1117,134 @@ declare class AgentModule {
1065
1117
  }>;
1066
1118
  }
1067
1119
 
1120
+ /**
1121
+ * ACP Agent Module — CLI-based agent sessions via ACP bridge
1122
+ *
1123
+ * Provides session lifecycle, sync/streaming chat, permission resolution,
1124
+ * and turn control for CLI agents (Claude, Gemini, Codex, etc.).
1125
+ *
1126
+ * Unlike AgentModule (LLM API-based), ACP agents spawn CLI processes
1127
+ * and can execute commands, read/write files, and interact with tools.
1128
+ */
1129
+
1130
+ interface AcpAgentInfo {
1131
+ id: string;
1132
+ label: string;
1133
+ handles: string[];
1134
+ installed: boolean;
1135
+ authReady: boolean;
1136
+ version?: string | null;
1137
+ status: "installed" | "not_installed";
1138
+ /** Present when listAgents({ includeModels: true }). */
1139
+ models?: Array<{
1140
+ id: string;
1141
+ name?: string;
1142
+ }>;
1143
+ /** "provider_api" | "fallback" — how models were resolved. */
1144
+ source?: string | null;
1145
+ /** Non-null if model fetch failed and fell back. */
1146
+ error?: string | null;
1147
+ }
1148
+ interface AcpSessionOptions {
1149
+ agent_id: string;
1150
+ cwd?: string;
1151
+ label?: string;
1152
+ model?: string;
1153
+ approvalPolicy?: "approve-all" | "approve-reads" | "deny-all";
1154
+ }
1155
+ interface AcpSession {
1156
+ session_key: string;
1157
+ agent_id: string;
1158
+ state: "initializing" | "ready" | "stale" | "closed";
1159
+ backend_id: string;
1160
+ created_at: string;
1161
+ }
1162
+ interface AcpSessionStatus extends AcpSession {
1163
+ runtime_options: AcpRuntimeOptionPatch;
1164
+ last_activity_at: string | null;
1165
+ last_error?: string;
1166
+ }
1167
+ interface AcpRuntimeOptionPatch {
1168
+ model?: string;
1169
+ cwd?: string;
1170
+ timeoutSeconds?: number;
1171
+ runtimeMode?: string;
1172
+ approvalPolicy?: "approve-all" | "approve-reads" | "deny-all";
1173
+ extras?: Record<string, string>;
1174
+ }
1175
+ interface AcpAttachment {
1176
+ contentString: string;
1177
+ mime: string;
1178
+ }
1179
+ interface AcpChatResponse {
1180
+ text: string;
1181
+ stop_reason?: string;
1182
+ }
1183
+ interface AcpStreamEvent {
1184
+ type: "text_delta" | "status" | "tool_call" | "permission_request" | "done" | "error" | "close";
1185
+ data: Record<string, unknown>;
1186
+ }
1187
+ interface AcpPermissionDecision {
1188
+ requestId: string;
1189
+ optionId: string;
1190
+ outcome?: string;
1191
+ }
1192
+ declare class AcpAgentModule {
1193
+ private httpClient;
1194
+ constructor(httpClient: HttpClient);
1195
+ /** List available CLI agents. Pass includeModels to get model lists per agent. */
1196
+ listAgents(opts?: {
1197
+ includeModels?: boolean;
1198
+ }): Promise<AcpAgentInfo[]>;
1199
+ /** Create and initialize a new ACP session. Spawns the CLI agent process. */
1200
+ createSession(options: AcpSessionOptions): Promise<AcpSession>;
1201
+ /** Get session status and runtime options. */
1202
+ getSession(sessionKey: string): Promise<AcpSessionStatus>;
1203
+ /** List active ACP sessions owned by this app. */
1204
+ listSessions(): Promise<AcpSessionStatus[]>;
1205
+ /** Update runtime options (applied on next turn). */
1206
+ patchSession(sessionKey: string, patch: AcpRuntimeOptionPatch): Promise<void>;
1207
+ /** Close session and stop the agent process. */
1208
+ closeSession(sessionKey: string, reason?: string): Promise<void>;
1209
+ /**
1210
+ * Synchronous turn — waits for completion, returns full response.
1211
+ * Requires approvalPolicy set on the session (via create or patchSession).
1212
+ */
1213
+ chat(sessionKey: string, message: string, attachments?: AcpAttachment[]): Promise<AcpChatResponse>;
1214
+ /**
1215
+ * Streaming turn via SSE. Yields events as they arrive.
1216
+ *
1217
+ * Uses named SSE events (event: + data: lines). The event type comes
1218
+ * from the `event:` line, not from inside the JSON payload.
1219
+ *
1220
+ * @example
1221
+ * ```typescript
1222
+ * for await (const event of sdk.acpAgent.streamChat(key, 'Explain this')) {
1223
+ * if (event.type === 'text_delta') console.log(event.data.text);
1224
+ * if (event.type === 'permission_request') {
1225
+ * await sdk.acpAgent.resolvePermission(key, {
1226
+ * requestId: event.data.requestId as string,
1227
+ * optionId: 'allow_once',
1228
+ * });
1229
+ * }
1230
+ * }
1231
+ * ```
1232
+ */
1233
+ streamChat(sessionKey: string, message: string, attachments?: AcpAttachment[]): AsyncIterableIterator<AcpStreamEvent>;
1234
+ /** Cancel the active turn on a session. */
1235
+ cancelTurn(sessionKey: string, reason?: string): Promise<void>;
1236
+ /** Resolve a pending permission request (call while SSE stream is active). */
1237
+ resolvePermission(sessionKey: string, decision: AcpPermissionDecision): Promise<{
1238
+ resolved: boolean;
1239
+ reason?: string;
1240
+ }>;
1241
+ /** Convenience: create session + first sync chat in one call. */
1242
+ startChat(message: string, options: AcpSessionOptions): Promise<{
1243
+ session: AcpSession;
1244
+ response: AcpChatResponse;
1245
+ }>;
1246
+ }
1247
+
1068
1248
  /**
1069
1249
  * MCP Module - Interact with MCP servers via RealtimeX SDK
1070
1250
  */
@@ -1170,10 +1350,19 @@ declare class ContractModule {
1170
1350
  private readonly appId?;
1171
1351
  private readonly apiKey?;
1172
1352
  private cachedContract;
1353
+ private cachedCapabilities;
1354
+ private cachedCapabilityCatalogHash;
1173
1355
  constructor(realtimexUrl: string, appName?: string, appId?: string, apiKey?: string);
1174
1356
  private requestPermission;
1175
1357
  private request;
1176
1358
  getLocalAppV1(forceRefresh?: boolean): Promise<LocalAppContractDefinition>;
1359
+ listCapabilities(forceRefresh?: boolean): Promise<ContractCapability$1[]>;
1360
+ searchCapabilities(query: string): Promise<ContractCapability$1[]>;
1361
+ describeCapability(capabilityId: string): Promise<ContractCapability$1>;
1362
+ search(query: string): Promise<ContractCapability$1[]>;
1363
+ describe(capabilityId: string): Promise<ContractCapability$1>;
1364
+ invoke(payload: ContractInvokePayload): Promise<TriggerAgentResponse>;
1365
+ getCachedCatalogHash(): string | null;
1177
1366
  clearCache(): void;
1178
1367
  }
1179
1368
 
@@ -1786,6 +1975,7 @@ declare class RealtimeXSDK {
1786
1975
  tts: TTSModule;
1787
1976
  stt: STTModule;
1788
1977
  agent: AgentModule;
1978
+ acpAgent: AcpAgentModule;
1789
1979
  mcp: MCPModule;
1790
1980
  contract: ContractModule;
1791
1981
  contractRuntime: ContractRuntime;
@@ -1825,4 +2015,4 @@ declare class RealtimeXSDK {
1825
2015
  getAppDataDir(): Promise<string>;
1826
2016
  }
1827
2017
 
1828
- export { type ACPAdapterContext, type ACPAdapterTelemetryEvent, type ACPAdapterTelemetrySink, ACPContractAdapter, type ACPContractAdapterOptions, type ACPContractRuntime, ACPEventMapper, type ACPExecutionReference, type ACPNotifier, ACPPermissionBridge, type ACPSessionToolUpdate, type ACPSessionUpdateParams, ACPTelemetry, type ACPTextContent, type ACPToolInvocation, type ACPToolKind, type ACPToolStatus, ActivitiesModule, type Activity, type Agent, type AgentChatOptions, type AgentChatResponse, AgentModule, type AgentSession, type AgentSessionInfo, type AgentSessionOptions, ApiModule, AuthModule, type AuthProvider, type AuthTokenResponse, CONTRACT_ATTEMPT_PREFIX, CONTRACT_EVENT_ID_HEADER, CONTRACT_SIGNATURE_ALGORITHM, CONTRACT_SIGNATURE_HEADER, type CanonicalToolDefinition, type ChatContentBlock, type ChatCustomBlock, type ChatFileBlock, type ChatImageUrlBlock, type ChatMessage, type ChatMessageContent, type ChatOptions, type ChatResponse, type ChatTextBlock, ClaudeToolAdapter, type ClaudeToolCall, type ClaudeToolDefinition, type ClaudeToolResult, CodexToolAdapter, type CodexToolCall, type CodexToolDefinition, type CodexToolResult, ContractCache, type ContractCallbackMetadata, type ContractCallbackRules, type ContractCapability, type ContractCapabilityTrigger, ContractClient, type ContractClientOptions, type ContractDiscoveryResponse, ContractError, type ContractEventType, ContractHttpClient, type ContractHttpClientConfig, ContractModule, ContractRuntime, type ContractRuntimeInterface, type ContractRuntimeOptions, type ContractSignInput, type ContractStrictness, ContractValidationError, type DatabaseConfig, DatabaseModule, type EmbedOptions, type EmbedResponse, type ExecutionContext, type ExecutionResult, type GeminiFunctionDeclaration, GeminiToolAdapter, type GeminiToolCall, type GeminiToolResult, type GetToolsInput, type HostToolAdapter, type IngestExecutionEventInput, LLMModule, LLMPermissionError, LLMProviderError, LOCAL_APP_CONTRACT_VERSION, type LegacyLocalAppContractShape, type LifecycleEventType, type LocalAppContractDefinition, type LocalAppContractResponse, type LocalAppContractV1, MCPModule, type MCPServer, type MCPTool, type MCPToolResult, PermissionDeniedError, type PermissionOption, PermissionRequiredError, PortModule, type ProjectToolsInput, type Provider, type ProviderKind, type ProvidersResponse, RealtimeXSDK, RetryPolicy, type RetryPolicyOptions, type RuntimeExecutionEvent, RuntimeTransportError, type SDKConfig, type STTListenOptions, type STTModel, type STTModelsResponse, STTModule, type STTProvider, type STTProvidersResponse, type STTResponse, ScopeDeniedError, ScopeGuard, StaticAuthProvider, type StaticAuthProviderOptions, type StreamChunk, type StreamChunkEvent, type SyncTokenResponse, type TTSChunk, type TTSChunkEvent, TTSModule, type TTSOptions, type TTSProvider, type TTSProviderConfig, type TTSProvidersResponse, type Task, TaskModule, type TaskRun, type Thread, type ToolCall, ToolNotFoundError, ToolProjector, ToolValidationError, type TriggerAgentPayload, type TriggerAgentResponse, type VectorDeleteOptions, type VectorDeleteResponse, type VectorQueryOptions, type VectorQueryResponse, type VectorQueryResult, type VectorRecord, VectorStore, type VectorUpsertOptions, type VectorUpsertResponse, WebhookModule, type Workspace, buildContractIdempotencyKey, buildContractSignatureMessage, canonicalEventToLegacyAction, createContractEventId, hashContractPayload, normalizeAttemptId, normalizeContractEvent, normalizeLocalAppContractV1, normalizeSchema, parseAttemptRunId, signContractEvent, toStableToolName };
2018
+ export { type ACPAdapterContext, type ACPAdapterTelemetryEvent, type ACPAdapterTelemetrySink, ACPContractAdapter, type ACPContractAdapterOptions, type ACPContractRuntime, ACPEventMapper, type ACPExecutionReference, type ACPNotifier, ACPPermissionBridge, type ACPSessionToolUpdate, type ACPSessionUpdateParams, ACPTelemetry, type ACPTextContent, type ACPToolInvocation, type ACPToolKind, type ACPToolStatus, type AcpAgentInfo, AcpAgentModule, type AcpAttachment, type AcpChatResponse, type AcpPermissionDecision, type AcpRuntimeOptionPatch, type AcpSession, type AcpSessionOptions, type AcpSessionStatus, type AcpStreamEvent, ActivitiesModule, type Activity, type Agent, type AgentChatOptions, type AgentChatResponse, AgentModule, type AgentSession, type AgentSessionInfo, type AgentSessionOptions, ApiModule, AuthModule, type AuthProvider, type AuthTokenResponse, CONTRACT_ATTEMPT_PREFIX, CONTRACT_EVENT_ID_HEADER, CONTRACT_SIGNATURE_ALGORITHM, CONTRACT_SIGNATURE_HEADER, type CanonicalToolDefinition, type ChatContentBlock, type ChatCustomBlock, type ChatFileBlock, type ChatImageUrlBlock, type ChatMessage, type ChatMessageContent, type ChatOptions, type ChatResponse, type ChatTextBlock, ClaudeToolAdapter, type ClaudeToolCall, type ClaudeToolDefinition, type ClaudeToolResult, CodexToolAdapter, type CodexToolCall, type CodexToolDefinition, type CodexToolResult, ContractCache, type ContractCallbackMetadata, type ContractCallbackRules, type ContractCapability, type ContractCapabilityTrigger, ContractClient, type ContractClientOptions, type ContractDiscoveryResponse, ContractError, type ContractEventType, ContractHttpClient, type ContractHttpClientConfig, type ContractInvokePayload, ContractModule, ContractRuntime, type ContractRuntimeInterface, type ContractRuntimeOptions, type ContractSignInput, type ContractStrictness, ContractValidationError, type DatabaseConfig, DatabaseModule, type EmbedOptions, type EmbedResponse, type ExecutionContext, type ExecutionResult, type GeminiFunctionDeclaration, GeminiToolAdapter, type GeminiToolCall, type GeminiToolResult, type GetToolsInput, type HostToolAdapter, type IngestExecutionEventInput, LLMModule, LLMPermissionError, LLMProviderError, LOCAL_APP_CONTRACT_VERSION, type LegacyLocalAppContractShape, type LifecycleEventType, type LocalAppCapabilitiesResponse, type LocalAppCapabilityDetailResponse, type LocalAppCapabilitySearchResponse, type LocalAppContractDefinition, type LocalAppContractResponse, type LocalAppContractV1, MCPModule, type MCPServer, type MCPTool, type MCPToolResult, PermissionDeniedError, type PermissionOption, PermissionRequiredError, PortModule, type ProjectToolsInput, type Provider, type ProviderKind, type ProvidersResponse, RealtimeXSDK, RetryPolicy, type RetryPolicyOptions, type RuntimeExecutionEvent, RuntimeTransportError, type SDKConfig, type STTListenOptions, type STTModel, type STTModelsResponse, STTModule, type STTProvider, type STTProvidersResponse, type STTResponse, ScopeDeniedError, ScopeGuard, StaticAuthProvider, type StaticAuthProviderOptions, type StreamChunk, type StreamChunkEvent, type SyncTokenResponse, type TTSChunk, type TTSChunkEvent, TTSModule, type TTSOptions, type TTSProvider, type TTSProviderConfig, type TTSProvidersResponse, type Task, TaskModule, type TaskRun, type Thread, type ToolCall, ToolNotFoundError, ToolProjector, ToolValidationError, type TriggerAgentPayload, type TriggerAgentResponse, type VectorDeleteOptions, type VectorDeleteResponse, type VectorQueryOptions, type VectorQueryResponse, type VectorQueryResult, type VectorRecord, VectorStore, type VectorUpsertOptions, type VectorUpsertResponse, WebhookModule, type Workspace, buildContractIdempotencyKey, buildContractSignatureMessage, canonicalEventToLegacyAction, createContractEventId, hashContractPayload, normalizeAttemptId, normalizeContractEvent, normalizeLocalAppContractV1, normalizeSchema, parseAttemptRunId, signContractEvent, toStableToolName };
package/dist/index.d.ts CHANGED
@@ -41,6 +41,7 @@ interface TriggerAgentResponse {
41
41
  success: boolean;
42
42
  task_uuid?: string;
43
43
  task_id?: string;
44
+ capability_id?: string;
44
45
  event_id?: string;
45
46
  attempt_id?: string;
46
47
  event_type?: ContractEventType | string;
@@ -59,21 +60,72 @@ interface ContractCallbackMetadata {
59
60
  attempt_id_format?: string;
60
61
  idempotency?: string;
61
62
  }
63
+ interface ContractCapabilityTrigger$1 {
64
+ event: string;
65
+ route?: string;
66
+ payload_template?: Record<string, unknown>;
67
+ }
68
+ interface ContractCapability$1 {
69
+ capability_id: string;
70
+ name: string;
71
+ description?: string;
72
+ input_schema: Record<string, unknown>;
73
+ output_schema?: Record<string, unknown>;
74
+ permission?: string;
75
+ trigger?: ContractCapabilityTrigger$1;
76
+ tags?: string[];
77
+ examples?: string[];
78
+ risk_level?: 'low' | 'medium' | 'high' | null;
79
+ enabled?: boolean;
80
+ }
62
81
  interface LocalAppContractDefinition {
63
82
  id: string;
64
83
  version: string;
84
+ strictness?: 'compatible' | 'strict';
65
85
  events: Record<string, ContractEventType>;
66
86
  supported_events: ContractEventType[];
67
87
  supported_legacy_events: string[];
68
88
  aliases: Record<string, ContractEventType>;
69
89
  status_map: Record<string, string>;
70
90
  legacy_action_map: Record<ContractEventType, string>;
91
+ catalog_hash?: string;
92
+ capability_count?: number;
93
+ capabilities?: ContractCapability$1[];
71
94
  callback?: ContractCallbackMetadata;
72
95
  }
73
96
  interface LocalAppContractResponse {
74
97
  success: boolean;
75
98
  contract: LocalAppContractDefinition;
76
99
  }
100
+ interface LocalAppCapabilitiesResponse {
101
+ success: boolean;
102
+ contract_version: string;
103
+ strictness?: 'compatible' | 'strict';
104
+ catalog_hash?: string;
105
+ count: number;
106
+ capabilities: ContractCapability$1[];
107
+ }
108
+ interface LocalAppCapabilitySearchResponse extends LocalAppCapabilitiesResponse {
109
+ query: string;
110
+ }
111
+ interface LocalAppCapabilityDetailResponse {
112
+ success: boolean;
113
+ contract_version: string;
114
+ strictness?: 'compatible' | 'strict';
115
+ catalog_hash?: string;
116
+ capability: ContractCapability$1;
117
+ }
118
+ interface ContractInvokePayload {
119
+ capability_id: string;
120
+ args?: Record<string, unknown>;
121
+ auto_run?: boolean;
122
+ agent_name?: string;
123
+ workspace_slug?: string;
124
+ thread_slug?: string;
125
+ prompt?: string;
126
+ event_id?: string;
127
+ attempt_id?: string | number;
128
+ }
77
129
  interface Agent {
78
130
  slug: string;
79
131
  name: string;
@@ -1065,6 +1117,134 @@ declare class AgentModule {
1065
1117
  }>;
1066
1118
  }
1067
1119
 
1120
+ /**
1121
+ * ACP Agent Module — CLI-based agent sessions via ACP bridge
1122
+ *
1123
+ * Provides session lifecycle, sync/streaming chat, permission resolution,
1124
+ * and turn control for CLI agents (Claude, Gemini, Codex, etc.).
1125
+ *
1126
+ * Unlike AgentModule (LLM API-based), ACP agents spawn CLI processes
1127
+ * and can execute commands, read/write files, and interact with tools.
1128
+ */
1129
+
1130
+ interface AcpAgentInfo {
1131
+ id: string;
1132
+ label: string;
1133
+ handles: string[];
1134
+ installed: boolean;
1135
+ authReady: boolean;
1136
+ version?: string | null;
1137
+ status: "installed" | "not_installed";
1138
+ /** Present when listAgents({ includeModels: true }). */
1139
+ models?: Array<{
1140
+ id: string;
1141
+ name?: string;
1142
+ }>;
1143
+ /** "provider_api" | "fallback" — how models were resolved. */
1144
+ source?: string | null;
1145
+ /** Non-null if model fetch failed and fell back. */
1146
+ error?: string | null;
1147
+ }
1148
+ interface AcpSessionOptions {
1149
+ agent_id: string;
1150
+ cwd?: string;
1151
+ label?: string;
1152
+ model?: string;
1153
+ approvalPolicy?: "approve-all" | "approve-reads" | "deny-all";
1154
+ }
1155
+ interface AcpSession {
1156
+ session_key: string;
1157
+ agent_id: string;
1158
+ state: "initializing" | "ready" | "stale" | "closed";
1159
+ backend_id: string;
1160
+ created_at: string;
1161
+ }
1162
+ interface AcpSessionStatus extends AcpSession {
1163
+ runtime_options: AcpRuntimeOptionPatch;
1164
+ last_activity_at: string | null;
1165
+ last_error?: string;
1166
+ }
1167
+ interface AcpRuntimeOptionPatch {
1168
+ model?: string;
1169
+ cwd?: string;
1170
+ timeoutSeconds?: number;
1171
+ runtimeMode?: string;
1172
+ approvalPolicy?: "approve-all" | "approve-reads" | "deny-all";
1173
+ extras?: Record<string, string>;
1174
+ }
1175
+ interface AcpAttachment {
1176
+ contentString: string;
1177
+ mime: string;
1178
+ }
1179
+ interface AcpChatResponse {
1180
+ text: string;
1181
+ stop_reason?: string;
1182
+ }
1183
+ interface AcpStreamEvent {
1184
+ type: "text_delta" | "status" | "tool_call" | "permission_request" | "done" | "error" | "close";
1185
+ data: Record<string, unknown>;
1186
+ }
1187
+ interface AcpPermissionDecision {
1188
+ requestId: string;
1189
+ optionId: string;
1190
+ outcome?: string;
1191
+ }
1192
+ declare class AcpAgentModule {
1193
+ private httpClient;
1194
+ constructor(httpClient: HttpClient);
1195
+ /** List available CLI agents. Pass includeModels to get model lists per agent. */
1196
+ listAgents(opts?: {
1197
+ includeModels?: boolean;
1198
+ }): Promise<AcpAgentInfo[]>;
1199
+ /** Create and initialize a new ACP session. Spawns the CLI agent process. */
1200
+ createSession(options: AcpSessionOptions): Promise<AcpSession>;
1201
+ /** Get session status and runtime options. */
1202
+ getSession(sessionKey: string): Promise<AcpSessionStatus>;
1203
+ /** List active ACP sessions owned by this app. */
1204
+ listSessions(): Promise<AcpSessionStatus[]>;
1205
+ /** Update runtime options (applied on next turn). */
1206
+ patchSession(sessionKey: string, patch: AcpRuntimeOptionPatch): Promise<void>;
1207
+ /** Close session and stop the agent process. */
1208
+ closeSession(sessionKey: string, reason?: string): Promise<void>;
1209
+ /**
1210
+ * Synchronous turn — waits for completion, returns full response.
1211
+ * Requires approvalPolicy set on the session (via create or patchSession).
1212
+ */
1213
+ chat(sessionKey: string, message: string, attachments?: AcpAttachment[]): Promise<AcpChatResponse>;
1214
+ /**
1215
+ * Streaming turn via SSE. Yields events as they arrive.
1216
+ *
1217
+ * Uses named SSE events (event: + data: lines). The event type comes
1218
+ * from the `event:` line, not from inside the JSON payload.
1219
+ *
1220
+ * @example
1221
+ * ```typescript
1222
+ * for await (const event of sdk.acpAgent.streamChat(key, 'Explain this')) {
1223
+ * if (event.type === 'text_delta') console.log(event.data.text);
1224
+ * if (event.type === 'permission_request') {
1225
+ * await sdk.acpAgent.resolvePermission(key, {
1226
+ * requestId: event.data.requestId as string,
1227
+ * optionId: 'allow_once',
1228
+ * });
1229
+ * }
1230
+ * }
1231
+ * ```
1232
+ */
1233
+ streamChat(sessionKey: string, message: string, attachments?: AcpAttachment[]): AsyncIterableIterator<AcpStreamEvent>;
1234
+ /** Cancel the active turn on a session. */
1235
+ cancelTurn(sessionKey: string, reason?: string): Promise<void>;
1236
+ /** Resolve a pending permission request (call while SSE stream is active). */
1237
+ resolvePermission(sessionKey: string, decision: AcpPermissionDecision): Promise<{
1238
+ resolved: boolean;
1239
+ reason?: string;
1240
+ }>;
1241
+ /** Convenience: create session + first sync chat in one call. */
1242
+ startChat(message: string, options: AcpSessionOptions): Promise<{
1243
+ session: AcpSession;
1244
+ response: AcpChatResponse;
1245
+ }>;
1246
+ }
1247
+
1068
1248
  /**
1069
1249
  * MCP Module - Interact with MCP servers via RealtimeX SDK
1070
1250
  */
@@ -1170,10 +1350,19 @@ declare class ContractModule {
1170
1350
  private readonly appId?;
1171
1351
  private readonly apiKey?;
1172
1352
  private cachedContract;
1353
+ private cachedCapabilities;
1354
+ private cachedCapabilityCatalogHash;
1173
1355
  constructor(realtimexUrl: string, appName?: string, appId?: string, apiKey?: string);
1174
1356
  private requestPermission;
1175
1357
  private request;
1176
1358
  getLocalAppV1(forceRefresh?: boolean): Promise<LocalAppContractDefinition>;
1359
+ listCapabilities(forceRefresh?: boolean): Promise<ContractCapability$1[]>;
1360
+ searchCapabilities(query: string): Promise<ContractCapability$1[]>;
1361
+ describeCapability(capabilityId: string): Promise<ContractCapability$1>;
1362
+ search(query: string): Promise<ContractCapability$1[]>;
1363
+ describe(capabilityId: string): Promise<ContractCapability$1>;
1364
+ invoke(payload: ContractInvokePayload): Promise<TriggerAgentResponse>;
1365
+ getCachedCatalogHash(): string | null;
1177
1366
  clearCache(): void;
1178
1367
  }
1179
1368
 
@@ -1786,6 +1975,7 @@ declare class RealtimeXSDK {
1786
1975
  tts: TTSModule;
1787
1976
  stt: STTModule;
1788
1977
  agent: AgentModule;
1978
+ acpAgent: AcpAgentModule;
1789
1979
  mcp: MCPModule;
1790
1980
  contract: ContractModule;
1791
1981
  contractRuntime: ContractRuntime;
@@ -1825,4 +2015,4 @@ declare class RealtimeXSDK {
1825
2015
  getAppDataDir(): Promise<string>;
1826
2016
  }
1827
2017
 
1828
- export { type ACPAdapterContext, type ACPAdapterTelemetryEvent, type ACPAdapterTelemetrySink, ACPContractAdapter, type ACPContractAdapterOptions, type ACPContractRuntime, ACPEventMapper, type ACPExecutionReference, type ACPNotifier, ACPPermissionBridge, type ACPSessionToolUpdate, type ACPSessionUpdateParams, ACPTelemetry, type ACPTextContent, type ACPToolInvocation, type ACPToolKind, type ACPToolStatus, ActivitiesModule, type Activity, type Agent, type AgentChatOptions, type AgentChatResponse, AgentModule, type AgentSession, type AgentSessionInfo, type AgentSessionOptions, ApiModule, AuthModule, type AuthProvider, type AuthTokenResponse, CONTRACT_ATTEMPT_PREFIX, CONTRACT_EVENT_ID_HEADER, CONTRACT_SIGNATURE_ALGORITHM, CONTRACT_SIGNATURE_HEADER, type CanonicalToolDefinition, type ChatContentBlock, type ChatCustomBlock, type ChatFileBlock, type ChatImageUrlBlock, type ChatMessage, type ChatMessageContent, type ChatOptions, type ChatResponse, type ChatTextBlock, ClaudeToolAdapter, type ClaudeToolCall, type ClaudeToolDefinition, type ClaudeToolResult, CodexToolAdapter, type CodexToolCall, type CodexToolDefinition, type CodexToolResult, ContractCache, type ContractCallbackMetadata, type ContractCallbackRules, type ContractCapability, type ContractCapabilityTrigger, ContractClient, type ContractClientOptions, type ContractDiscoveryResponse, ContractError, type ContractEventType, ContractHttpClient, type ContractHttpClientConfig, ContractModule, ContractRuntime, type ContractRuntimeInterface, type ContractRuntimeOptions, type ContractSignInput, type ContractStrictness, ContractValidationError, type DatabaseConfig, DatabaseModule, type EmbedOptions, type EmbedResponse, type ExecutionContext, type ExecutionResult, type GeminiFunctionDeclaration, GeminiToolAdapter, type GeminiToolCall, type GeminiToolResult, type GetToolsInput, type HostToolAdapter, type IngestExecutionEventInput, LLMModule, LLMPermissionError, LLMProviderError, LOCAL_APP_CONTRACT_VERSION, type LegacyLocalAppContractShape, type LifecycleEventType, type LocalAppContractDefinition, type LocalAppContractResponse, type LocalAppContractV1, MCPModule, type MCPServer, type MCPTool, type MCPToolResult, PermissionDeniedError, type PermissionOption, PermissionRequiredError, PortModule, type ProjectToolsInput, type Provider, type ProviderKind, type ProvidersResponse, RealtimeXSDK, RetryPolicy, type RetryPolicyOptions, type RuntimeExecutionEvent, RuntimeTransportError, type SDKConfig, type STTListenOptions, type STTModel, type STTModelsResponse, STTModule, type STTProvider, type STTProvidersResponse, type STTResponse, ScopeDeniedError, ScopeGuard, StaticAuthProvider, type StaticAuthProviderOptions, type StreamChunk, type StreamChunkEvent, type SyncTokenResponse, type TTSChunk, type TTSChunkEvent, TTSModule, type TTSOptions, type TTSProvider, type TTSProviderConfig, type TTSProvidersResponse, type Task, TaskModule, type TaskRun, type Thread, type ToolCall, ToolNotFoundError, ToolProjector, ToolValidationError, type TriggerAgentPayload, type TriggerAgentResponse, type VectorDeleteOptions, type VectorDeleteResponse, type VectorQueryOptions, type VectorQueryResponse, type VectorQueryResult, type VectorRecord, VectorStore, type VectorUpsertOptions, type VectorUpsertResponse, WebhookModule, type Workspace, buildContractIdempotencyKey, buildContractSignatureMessage, canonicalEventToLegacyAction, createContractEventId, hashContractPayload, normalizeAttemptId, normalizeContractEvent, normalizeLocalAppContractV1, normalizeSchema, parseAttemptRunId, signContractEvent, toStableToolName };
2018
+ export { type ACPAdapterContext, type ACPAdapterTelemetryEvent, type ACPAdapterTelemetrySink, ACPContractAdapter, type ACPContractAdapterOptions, type ACPContractRuntime, ACPEventMapper, type ACPExecutionReference, type ACPNotifier, ACPPermissionBridge, type ACPSessionToolUpdate, type ACPSessionUpdateParams, ACPTelemetry, type ACPTextContent, type ACPToolInvocation, type ACPToolKind, type ACPToolStatus, type AcpAgentInfo, AcpAgentModule, type AcpAttachment, type AcpChatResponse, type AcpPermissionDecision, type AcpRuntimeOptionPatch, type AcpSession, type AcpSessionOptions, type AcpSessionStatus, type AcpStreamEvent, ActivitiesModule, type Activity, type Agent, type AgentChatOptions, type AgentChatResponse, AgentModule, type AgentSession, type AgentSessionInfo, type AgentSessionOptions, ApiModule, AuthModule, type AuthProvider, type AuthTokenResponse, CONTRACT_ATTEMPT_PREFIX, CONTRACT_EVENT_ID_HEADER, CONTRACT_SIGNATURE_ALGORITHM, CONTRACT_SIGNATURE_HEADER, type CanonicalToolDefinition, type ChatContentBlock, type ChatCustomBlock, type ChatFileBlock, type ChatImageUrlBlock, type ChatMessage, type ChatMessageContent, type ChatOptions, type ChatResponse, type ChatTextBlock, ClaudeToolAdapter, type ClaudeToolCall, type ClaudeToolDefinition, type ClaudeToolResult, CodexToolAdapter, type CodexToolCall, type CodexToolDefinition, type CodexToolResult, ContractCache, type ContractCallbackMetadata, type ContractCallbackRules, type ContractCapability, type ContractCapabilityTrigger, ContractClient, type ContractClientOptions, type ContractDiscoveryResponse, ContractError, type ContractEventType, ContractHttpClient, type ContractHttpClientConfig, type ContractInvokePayload, ContractModule, ContractRuntime, type ContractRuntimeInterface, type ContractRuntimeOptions, type ContractSignInput, type ContractStrictness, ContractValidationError, type DatabaseConfig, DatabaseModule, type EmbedOptions, type EmbedResponse, type ExecutionContext, type ExecutionResult, type GeminiFunctionDeclaration, GeminiToolAdapter, type GeminiToolCall, type GeminiToolResult, type GetToolsInput, type HostToolAdapter, type IngestExecutionEventInput, LLMModule, LLMPermissionError, LLMProviderError, LOCAL_APP_CONTRACT_VERSION, type LegacyLocalAppContractShape, type LifecycleEventType, type LocalAppCapabilitiesResponse, type LocalAppCapabilityDetailResponse, type LocalAppCapabilitySearchResponse, type LocalAppContractDefinition, type LocalAppContractResponse, type LocalAppContractV1, MCPModule, type MCPServer, type MCPTool, type MCPToolResult, PermissionDeniedError, type PermissionOption, PermissionRequiredError, PortModule, type ProjectToolsInput, type Provider, type ProviderKind, type ProvidersResponse, RealtimeXSDK, RetryPolicy, type RetryPolicyOptions, type RuntimeExecutionEvent, RuntimeTransportError, type SDKConfig, type STTListenOptions, type STTModel, type STTModelsResponse, STTModule, type STTProvider, type STTProvidersResponse, type STTResponse, ScopeDeniedError, ScopeGuard, StaticAuthProvider, type StaticAuthProviderOptions, type StreamChunk, type StreamChunkEvent, type SyncTokenResponse, type TTSChunk, type TTSChunkEvent, TTSModule, type TTSOptions, type TTSProvider, type TTSProviderConfig, type TTSProvidersResponse, type Task, TaskModule, type TaskRun, type Thread, type ToolCall, ToolNotFoundError, ToolProjector, ToolValidationError, type TriggerAgentPayload, type TriggerAgentResponse, type VectorDeleteOptions, type VectorDeleteResponse, type VectorQueryOptions, type VectorQueryResponse, type VectorQueryResult, type VectorRecord, VectorStore, type VectorUpsertOptions, type VectorUpsertResponse, WebhookModule, type Workspace, buildContractIdempotencyKey, buildContractSignatureMessage, canonicalEventToLegacyAction, createContractEventId, hashContractPayload, normalizeAttemptId, normalizeContractEvent, normalizeLocalAppContractV1, normalizeSchema, parseAttemptRunId, signContractEvent, toStableToolName };
package/dist/index.js CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  ACPEventMapper: () => ACPEventMapper,
35
35
  ACPPermissionBridge: () => ACPPermissionBridge,
36
36
  ACPTelemetry: () => ACPTelemetry,
37
+ AcpAgentModule: () => AcpAgentModule,
37
38
  ActivitiesModule: () => ActivitiesModule,
38
39
  AgentModule: () => AgentModule,
39
40
  ApiModule: () => ApiModule,
@@ -455,6 +456,8 @@ function buildContractIdempotencyKey({
455
456
  var ContractModule = class {
456
457
  constructor(realtimexUrl, appName, appId, apiKey) {
457
458
  this.cachedContract = null;
459
+ this.cachedCapabilities = null;
460
+ this.cachedCapabilityCatalogHash = null;
458
461
  this.realtimexUrl = realtimexUrl.replace(/\/$/, "");
459
462
  this.appName = appName;
460
463
  this.appId = appId;
@@ -477,16 +480,18 @@ var ContractModule = class {
477
480
  return false;
478
481
  }
479
482
  }
480
- async request(path) {
483
+ async request(path, options = {}) {
481
484
  const url = `${this.realtimexUrl}${path}`;
482
485
  const headers = {
483
- "Content-Type": "application/json"
486
+ "Content-Type": "application/json",
487
+ ...options.headers
484
488
  };
485
489
  if (this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`;
486
490
  if (this.appId) headers["x-app-id"] = this.appId;
487
491
  const response = await fetch(url, {
488
- method: "GET",
489
- headers
492
+ method: options.method || "GET",
493
+ headers,
494
+ body: options.body
490
495
  });
491
496
  const data = await response.json();
492
497
  if (response.status === 403) {
@@ -495,7 +500,7 @@ var ContractModule = class {
495
500
  const message = data.message;
496
501
  if (errorCode === "PERMISSION_REQUIRED" && permission) {
497
502
  const granted = await this.requestPermission(permission);
498
- if (granted) return this.request(path);
503
+ if (granted) return this.request(path, options);
499
504
  throw new PermissionDeniedError(permission, message);
500
505
  }
501
506
  if (errorCode === "PERMISSION_DENIED") {
@@ -511,10 +516,89 @@ var ContractModule = class {
511
516
  if (!forceRefresh && this.cachedContract) return this.cachedContract;
512
517
  const data = await this.request("/contracts/local-app/v1");
513
518
  this.cachedContract = data.contract;
519
+ if (Array.isArray(data.contract?.capabilities)) {
520
+ this.cachedCapabilities = data.contract.capabilities;
521
+ this.cachedCapabilityCatalogHash = data.contract.catalog_hash || null;
522
+ }
514
523
  return data.contract;
515
524
  }
525
+ async listCapabilities(forceRefresh = false) {
526
+ if (!forceRefresh && this.cachedCapabilities) return this.cachedCapabilities;
527
+ const data = await this.request(
528
+ "/contracts/local-app/v1/capabilities"
529
+ );
530
+ this.cachedCapabilities = Array.isArray(data.capabilities) ? data.capabilities : [];
531
+ this.cachedCapabilityCatalogHash = data.catalog_hash || null;
532
+ return this.cachedCapabilities;
533
+ }
534
+ async searchCapabilities(query) {
535
+ const normalizedQuery = String(query || "").trim();
536
+ if (!normalizedQuery) {
537
+ throw new Error("searchCapabilities requires a non-empty query");
538
+ }
539
+ const encodedQuery = encodeURIComponent(normalizedQuery);
540
+ const data = await this.request(
541
+ `/contracts/local-app/v1/capabilities/search?q=${encodedQuery}`
542
+ );
543
+ return Array.isArray(data.capabilities) ? data.capabilities : [];
544
+ }
545
+ async describeCapability(capabilityId) {
546
+ const normalizedCapabilityId = String(capabilityId || "").trim();
547
+ if (!normalizedCapabilityId) {
548
+ throw new Error("describeCapability requires a non-empty capability id");
549
+ }
550
+ const encodedCapabilityId = encodeURIComponent(normalizedCapabilityId);
551
+ const data = await this.request(
552
+ `/contracts/local-app/v1/capabilities/${encodedCapabilityId}`
553
+ );
554
+ return data.capability;
555
+ }
556
+ // Alias for agentic contract flow naming.
557
+ async search(query) {
558
+ return this.searchCapabilities(query);
559
+ }
560
+ // Alias for agentic contract flow naming.
561
+ async describe(capabilityId) {
562
+ return this.describeCapability(capabilityId);
563
+ }
564
+ async invoke(payload) {
565
+ const capabilityId = String(payload?.capability_id || "").trim();
566
+ if (!capabilityId) {
567
+ throw new Error("invoke requires payload.capability_id");
568
+ }
569
+ if (payload.auto_run && (!payload.agent_name || !payload.workspace_slug)) {
570
+ throw new Error("auto_run requires agent_name and workspace_slug");
571
+ }
572
+ const args = payload.args && typeof payload.args === "object" && !Array.isArray(payload.args) ? { ...payload.args } : {};
573
+ if (!args.capability) {
574
+ args.capability = capabilityId;
575
+ }
576
+ return this.request("/webhooks/realtimex", {
577
+ method: "POST",
578
+ body: JSON.stringify({
579
+ app_name: this.appName,
580
+ app_id: this.appId,
581
+ event: "task.trigger",
582
+ event_id: payload.event_id || createContractEventId(),
583
+ attempt_id: normalizeAttemptId(payload.attempt_id),
584
+ payload: {
585
+ raw_data: args,
586
+ auto_run: payload.auto_run ?? false,
587
+ agent_name: payload.agent_name,
588
+ workspace_slug: payload.workspace_slug,
589
+ thread_slug: payload.thread_slug,
590
+ prompt: payload.prompt ?? ""
591
+ }
592
+ })
593
+ });
594
+ }
595
+ getCachedCatalogHash() {
596
+ return this.cachedCapabilityCatalogHash;
597
+ }
516
598
  clearCache() {
517
599
  this.cachedContract = null;
600
+ this.cachedCapabilities = null;
601
+ this.cachedCapabilityCatalogHash = null;
518
602
  }
519
603
  };
520
604
 
@@ -1700,6 +1784,193 @@ var AgentModule = class {
1700
1784
  }
1701
1785
  };
1702
1786
 
1787
+ // src/modules/acpAgent.ts
1788
+ function encodeSessionKey(sessionKey) {
1789
+ return encodeURIComponent(sessionKey);
1790
+ }
1791
+ async function parseJsonResponse(response, fallbackError) {
1792
+ const data = await response.json();
1793
+ if (!response.ok) throw new Error(data.error || fallbackError);
1794
+ return data;
1795
+ }
1796
+ var AcpAgentModule = class {
1797
+ constructor(httpClient) {
1798
+ this.httpClient = httpClient;
1799
+ }
1800
+ /** List available CLI agents. Pass includeModels to get model lists per agent. */
1801
+ async listAgents(opts) {
1802
+ const qs = opts?.includeModels ? "?includeModels=true" : "";
1803
+ const response = await this.httpClient.fetch(`/sdk/acp/agents${qs}`);
1804
+ const data = await parseJsonResponse(
1805
+ response,
1806
+ "Failed to list agents"
1807
+ );
1808
+ return data.agents;
1809
+ }
1810
+ /** Create and initialize a new ACP session. Spawns the CLI agent process. */
1811
+ async createSession(options) {
1812
+ const response = await this.httpClient.fetch("/sdk/acp/session", {
1813
+ method: "POST",
1814
+ body: JSON.stringify(options)
1815
+ });
1816
+ const data = await parseJsonResponse(
1817
+ response,
1818
+ "Failed to create session"
1819
+ );
1820
+ return data.session;
1821
+ }
1822
+ /** Get session status and runtime options. */
1823
+ async getSession(sessionKey) {
1824
+ const response = await this.httpClient.fetch(
1825
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}`
1826
+ );
1827
+ const data = await parseJsonResponse(
1828
+ response,
1829
+ "Failed to get session"
1830
+ );
1831
+ return data.session;
1832
+ }
1833
+ /** List active ACP sessions owned by this app. */
1834
+ async listSessions() {
1835
+ const response = await this.httpClient.fetch("/sdk/acp/sessions");
1836
+ const data = await parseJsonResponse(
1837
+ response,
1838
+ "Failed to list sessions"
1839
+ );
1840
+ return data.sessions;
1841
+ }
1842
+ /** Update runtime options (applied on next turn). */
1843
+ async patchSession(sessionKey, patch) {
1844
+ const response = await this.httpClient.fetch(
1845
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}`,
1846
+ { method: "PATCH", body: JSON.stringify(patch) }
1847
+ );
1848
+ await parseJsonResponse(response, "Failed to update session");
1849
+ }
1850
+ /** Close session and stop the agent process. */
1851
+ async closeSession(sessionKey, reason) {
1852
+ const response = await this.httpClient.fetch(
1853
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}`,
1854
+ {
1855
+ method: "DELETE",
1856
+ body: reason ? JSON.stringify({ reason }) : void 0
1857
+ }
1858
+ );
1859
+ await parseJsonResponse(response, "Failed to close session");
1860
+ }
1861
+ /**
1862
+ * Synchronous turn — waits for completion, returns full response.
1863
+ * Requires approvalPolicy set on the session (via create or patchSession).
1864
+ */
1865
+ async chat(sessionKey, message, attachments) {
1866
+ const body = { message };
1867
+ if (attachments?.length) body.attachments = attachments;
1868
+ const response = await this.httpClient.fetch(
1869
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}/chat`,
1870
+ { method: "POST", body: JSON.stringify(body) }
1871
+ );
1872
+ const data = await parseJsonResponse(
1873
+ response,
1874
+ "Chat request failed"
1875
+ );
1876
+ return data.response;
1877
+ }
1878
+ /**
1879
+ * Streaming turn via SSE. Yields events as they arrive.
1880
+ *
1881
+ * Uses named SSE events (event: + data: lines). The event type comes
1882
+ * from the `event:` line, not from inside the JSON payload.
1883
+ *
1884
+ * @example
1885
+ * ```typescript
1886
+ * for await (const event of sdk.acpAgent.streamChat(key, 'Explain this')) {
1887
+ * if (event.type === 'text_delta') console.log(event.data.text);
1888
+ * if (event.type === 'permission_request') {
1889
+ * await sdk.acpAgent.resolvePermission(key, {
1890
+ * requestId: event.data.requestId as string,
1891
+ * optionId: 'allow_once',
1892
+ * });
1893
+ * }
1894
+ * }
1895
+ * ```
1896
+ */
1897
+ async *streamChat(sessionKey, message, attachments) {
1898
+ const body = { message };
1899
+ if (attachments?.length) body.attachments = attachments;
1900
+ const response = await this.httpClient.fetch(
1901
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}/chat/stream`,
1902
+ { method: "POST", body: JSON.stringify(body) }
1903
+ );
1904
+ if (!response.ok) {
1905
+ const data = await response.json();
1906
+ throw new Error(data.error || "Stream request failed");
1907
+ }
1908
+ if (!response.body) {
1909
+ throw new Error("Response body is null");
1910
+ }
1911
+ yield* parseNamedSSEStream(response.body);
1912
+ }
1913
+ /** Cancel the active turn on a session. */
1914
+ async cancelTurn(sessionKey, reason) {
1915
+ const response = await this.httpClient.fetch(
1916
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}/cancel`,
1917
+ {
1918
+ method: "POST",
1919
+ body: reason ? JSON.stringify({ reason }) : void 0
1920
+ }
1921
+ );
1922
+ await parseJsonResponse(response, "Failed to cancel turn");
1923
+ }
1924
+ /** Resolve a pending permission request (call while SSE stream is active). */
1925
+ async resolvePermission(sessionKey, decision) {
1926
+ const response = await this.httpClient.fetch(
1927
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}/permission`,
1928
+ { method: "POST", body: JSON.stringify(decision) }
1929
+ );
1930
+ return parseJsonResponse(response, "Failed to resolve permission");
1931
+ }
1932
+ /** Convenience: create session + first sync chat in one call. */
1933
+ async startChat(message, options) {
1934
+ const session = await this.createSession(options);
1935
+ const chatResponse = await this.chat(session.session_key, message);
1936
+ return { session, response: chatResponse };
1937
+ }
1938
+ };
1939
+ async function* parseNamedSSEStream(body) {
1940
+ const reader = body.getReader();
1941
+ const decoder = new TextDecoder();
1942
+ let buffer = "";
1943
+ let currentEvent = "";
1944
+ try {
1945
+ while (true) {
1946
+ const { done, value } = await reader.read();
1947
+ if (done) break;
1948
+ buffer += decoder.decode(value, { stream: true });
1949
+ const lines = buffer.split("\n");
1950
+ buffer = lines.pop() || "";
1951
+ for (const line of lines) {
1952
+ if (line.startsWith("event: ")) {
1953
+ currentEvent = line.slice(7).trim();
1954
+ } else if (line.startsWith("data: ")) {
1955
+ const jsonStr = line.slice(6);
1956
+ const eventType = currentEvent || void 0;
1957
+ currentEvent = "";
1958
+ if (!eventType) continue;
1959
+ try {
1960
+ const data = JSON.parse(jsonStr);
1961
+ yield { type: eventType, data };
1962
+ } catch {
1963
+ }
1964
+ } else if (line === "") {
1965
+ currentEvent = "";
1966
+ }
1967
+ }
1968
+ }
1969
+ } finally {
1970
+ reader.releaseLock();
1971
+ }
1972
+ }
1973
+
1703
1974
  // src/modules/mcp.ts
1704
1975
  var MCPModule = class extends ApiModule {
1705
1976
  constructor(realtimexUrl, appId, appName, apiKey) {
@@ -2497,6 +2768,7 @@ var ContractRuntime = class {
2497
2768
  tool_call_id: call.tool_call_id,
2498
2769
  args: call.args,
2499
2770
  context: {
2771
+ app_id: context.appId,
2500
2772
  user_id: context.userId,
2501
2773
  workspace_id: context.workspaceId || null,
2502
2774
  request_id: context.requestId || null,
@@ -2509,7 +2781,9 @@ var ContractRuntime = class {
2509
2781
  }
2510
2782
  return {
2511
2783
  app_name: this.appName,
2512
- app_id: this.appId || context.appId,
2784
+ // In API-key dev mode, app_id should be omitted unless explicitly configured
2785
+ // on the runtime. Passing an unknown app_id causes webhook trigger rejection.
2786
+ app_id: this.appId || void 0,
2513
2787
  event: tool.trigger.event,
2514
2788
  event_id: eventId,
2515
2789
  payload
@@ -3420,6 +3694,7 @@ var _RealtimeXSDK = class _RealtimeXSDK {
3420
3694
  this.tts = new TTSModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
3421
3695
  this.stt = new STTModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
3422
3696
  this.agent = new AgentModule(this.httpClient);
3697
+ this.acpAgent = new AcpAgentModule(this.httpClient);
3423
3698
  this.mcp = new MCPModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
3424
3699
  this.contract = new ContractModule(this.realtimexUrl, this.appName, this.appId, this.apiKey);
3425
3700
  this.contractRuntime = new ContractRuntime({
@@ -3536,6 +3811,7 @@ var RealtimeXSDK = _RealtimeXSDK;
3536
3811
  ACPEventMapper,
3537
3812
  ACPPermissionBridge,
3538
3813
  ACPTelemetry,
3814
+ AcpAgentModule,
3539
3815
  ActivitiesModule,
3540
3816
  AgentModule,
3541
3817
  ApiModule,
package/dist/index.mjs CHANGED
@@ -363,6 +363,8 @@ function buildContractIdempotencyKey({
363
363
  var ContractModule = class {
364
364
  constructor(realtimexUrl, appName, appId, apiKey) {
365
365
  this.cachedContract = null;
366
+ this.cachedCapabilities = null;
367
+ this.cachedCapabilityCatalogHash = null;
366
368
  this.realtimexUrl = realtimexUrl.replace(/\/$/, "");
367
369
  this.appName = appName;
368
370
  this.appId = appId;
@@ -385,16 +387,18 @@ var ContractModule = class {
385
387
  return false;
386
388
  }
387
389
  }
388
- async request(path) {
390
+ async request(path, options = {}) {
389
391
  const url = `${this.realtimexUrl}${path}`;
390
392
  const headers = {
391
- "Content-Type": "application/json"
393
+ "Content-Type": "application/json",
394
+ ...options.headers
392
395
  };
393
396
  if (this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`;
394
397
  if (this.appId) headers["x-app-id"] = this.appId;
395
398
  const response = await fetch(url, {
396
- method: "GET",
397
- headers
399
+ method: options.method || "GET",
400
+ headers,
401
+ body: options.body
398
402
  });
399
403
  const data = await response.json();
400
404
  if (response.status === 403) {
@@ -403,7 +407,7 @@ var ContractModule = class {
403
407
  const message = data.message;
404
408
  if (errorCode === "PERMISSION_REQUIRED" && permission) {
405
409
  const granted = await this.requestPermission(permission);
406
- if (granted) return this.request(path);
410
+ if (granted) return this.request(path, options);
407
411
  throw new PermissionDeniedError(permission, message);
408
412
  }
409
413
  if (errorCode === "PERMISSION_DENIED") {
@@ -419,10 +423,89 @@ var ContractModule = class {
419
423
  if (!forceRefresh && this.cachedContract) return this.cachedContract;
420
424
  const data = await this.request("/contracts/local-app/v1");
421
425
  this.cachedContract = data.contract;
426
+ if (Array.isArray(data.contract?.capabilities)) {
427
+ this.cachedCapabilities = data.contract.capabilities;
428
+ this.cachedCapabilityCatalogHash = data.contract.catalog_hash || null;
429
+ }
422
430
  return data.contract;
423
431
  }
432
+ async listCapabilities(forceRefresh = false) {
433
+ if (!forceRefresh && this.cachedCapabilities) return this.cachedCapabilities;
434
+ const data = await this.request(
435
+ "/contracts/local-app/v1/capabilities"
436
+ );
437
+ this.cachedCapabilities = Array.isArray(data.capabilities) ? data.capabilities : [];
438
+ this.cachedCapabilityCatalogHash = data.catalog_hash || null;
439
+ return this.cachedCapabilities;
440
+ }
441
+ async searchCapabilities(query) {
442
+ const normalizedQuery = String(query || "").trim();
443
+ if (!normalizedQuery) {
444
+ throw new Error("searchCapabilities requires a non-empty query");
445
+ }
446
+ const encodedQuery = encodeURIComponent(normalizedQuery);
447
+ const data = await this.request(
448
+ `/contracts/local-app/v1/capabilities/search?q=${encodedQuery}`
449
+ );
450
+ return Array.isArray(data.capabilities) ? data.capabilities : [];
451
+ }
452
+ async describeCapability(capabilityId) {
453
+ const normalizedCapabilityId = String(capabilityId || "").trim();
454
+ if (!normalizedCapabilityId) {
455
+ throw new Error("describeCapability requires a non-empty capability id");
456
+ }
457
+ const encodedCapabilityId = encodeURIComponent(normalizedCapabilityId);
458
+ const data = await this.request(
459
+ `/contracts/local-app/v1/capabilities/${encodedCapabilityId}`
460
+ );
461
+ return data.capability;
462
+ }
463
+ // Alias for agentic contract flow naming.
464
+ async search(query) {
465
+ return this.searchCapabilities(query);
466
+ }
467
+ // Alias for agentic contract flow naming.
468
+ async describe(capabilityId) {
469
+ return this.describeCapability(capabilityId);
470
+ }
471
+ async invoke(payload) {
472
+ const capabilityId = String(payload?.capability_id || "").trim();
473
+ if (!capabilityId) {
474
+ throw new Error("invoke requires payload.capability_id");
475
+ }
476
+ if (payload.auto_run && (!payload.agent_name || !payload.workspace_slug)) {
477
+ throw new Error("auto_run requires agent_name and workspace_slug");
478
+ }
479
+ const args = payload.args && typeof payload.args === "object" && !Array.isArray(payload.args) ? { ...payload.args } : {};
480
+ if (!args.capability) {
481
+ args.capability = capabilityId;
482
+ }
483
+ return this.request("/webhooks/realtimex", {
484
+ method: "POST",
485
+ body: JSON.stringify({
486
+ app_name: this.appName,
487
+ app_id: this.appId,
488
+ event: "task.trigger",
489
+ event_id: payload.event_id || createContractEventId(),
490
+ attempt_id: normalizeAttemptId(payload.attempt_id),
491
+ payload: {
492
+ raw_data: args,
493
+ auto_run: payload.auto_run ?? false,
494
+ agent_name: payload.agent_name,
495
+ workspace_slug: payload.workspace_slug,
496
+ thread_slug: payload.thread_slug,
497
+ prompt: payload.prompt ?? ""
498
+ }
499
+ })
500
+ });
501
+ }
502
+ getCachedCatalogHash() {
503
+ return this.cachedCapabilityCatalogHash;
504
+ }
424
505
  clearCache() {
425
506
  this.cachedContract = null;
507
+ this.cachedCapabilities = null;
508
+ this.cachedCapabilityCatalogHash = null;
426
509
  }
427
510
  };
428
511
 
@@ -1608,6 +1691,193 @@ var AgentModule = class {
1608
1691
  }
1609
1692
  };
1610
1693
 
1694
+ // src/modules/acpAgent.ts
1695
+ function encodeSessionKey(sessionKey) {
1696
+ return encodeURIComponent(sessionKey);
1697
+ }
1698
+ async function parseJsonResponse(response, fallbackError) {
1699
+ const data = await response.json();
1700
+ if (!response.ok) throw new Error(data.error || fallbackError);
1701
+ return data;
1702
+ }
1703
+ var AcpAgentModule = class {
1704
+ constructor(httpClient) {
1705
+ this.httpClient = httpClient;
1706
+ }
1707
+ /** List available CLI agents. Pass includeModels to get model lists per agent. */
1708
+ async listAgents(opts) {
1709
+ const qs = opts?.includeModels ? "?includeModels=true" : "";
1710
+ const response = await this.httpClient.fetch(`/sdk/acp/agents${qs}`);
1711
+ const data = await parseJsonResponse(
1712
+ response,
1713
+ "Failed to list agents"
1714
+ );
1715
+ return data.agents;
1716
+ }
1717
+ /** Create and initialize a new ACP session. Spawns the CLI agent process. */
1718
+ async createSession(options) {
1719
+ const response = await this.httpClient.fetch("/sdk/acp/session", {
1720
+ method: "POST",
1721
+ body: JSON.stringify(options)
1722
+ });
1723
+ const data = await parseJsonResponse(
1724
+ response,
1725
+ "Failed to create session"
1726
+ );
1727
+ return data.session;
1728
+ }
1729
+ /** Get session status and runtime options. */
1730
+ async getSession(sessionKey) {
1731
+ const response = await this.httpClient.fetch(
1732
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}`
1733
+ );
1734
+ const data = await parseJsonResponse(
1735
+ response,
1736
+ "Failed to get session"
1737
+ );
1738
+ return data.session;
1739
+ }
1740
+ /** List active ACP sessions owned by this app. */
1741
+ async listSessions() {
1742
+ const response = await this.httpClient.fetch("/sdk/acp/sessions");
1743
+ const data = await parseJsonResponse(
1744
+ response,
1745
+ "Failed to list sessions"
1746
+ );
1747
+ return data.sessions;
1748
+ }
1749
+ /** Update runtime options (applied on next turn). */
1750
+ async patchSession(sessionKey, patch) {
1751
+ const response = await this.httpClient.fetch(
1752
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}`,
1753
+ { method: "PATCH", body: JSON.stringify(patch) }
1754
+ );
1755
+ await parseJsonResponse(response, "Failed to update session");
1756
+ }
1757
+ /** Close session and stop the agent process. */
1758
+ async closeSession(sessionKey, reason) {
1759
+ const response = await this.httpClient.fetch(
1760
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}`,
1761
+ {
1762
+ method: "DELETE",
1763
+ body: reason ? JSON.stringify({ reason }) : void 0
1764
+ }
1765
+ );
1766
+ await parseJsonResponse(response, "Failed to close session");
1767
+ }
1768
+ /**
1769
+ * Synchronous turn — waits for completion, returns full response.
1770
+ * Requires approvalPolicy set on the session (via create or patchSession).
1771
+ */
1772
+ async chat(sessionKey, message, attachments) {
1773
+ const body = { message };
1774
+ if (attachments?.length) body.attachments = attachments;
1775
+ const response = await this.httpClient.fetch(
1776
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}/chat`,
1777
+ { method: "POST", body: JSON.stringify(body) }
1778
+ );
1779
+ const data = await parseJsonResponse(
1780
+ response,
1781
+ "Chat request failed"
1782
+ );
1783
+ return data.response;
1784
+ }
1785
+ /**
1786
+ * Streaming turn via SSE. Yields events as they arrive.
1787
+ *
1788
+ * Uses named SSE events (event: + data: lines). The event type comes
1789
+ * from the `event:` line, not from inside the JSON payload.
1790
+ *
1791
+ * @example
1792
+ * ```typescript
1793
+ * for await (const event of sdk.acpAgent.streamChat(key, 'Explain this')) {
1794
+ * if (event.type === 'text_delta') console.log(event.data.text);
1795
+ * if (event.type === 'permission_request') {
1796
+ * await sdk.acpAgent.resolvePermission(key, {
1797
+ * requestId: event.data.requestId as string,
1798
+ * optionId: 'allow_once',
1799
+ * });
1800
+ * }
1801
+ * }
1802
+ * ```
1803
+ */
1804
+ async *streamChat(sessionKey, message, attachments) {
1805
+ const body = { message };
1806
+ if (attachments?.length) body.attachments = attachments;
1807
+ const response = await this.httpClient.fetch(
1808
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}/chat/stream`,
1809
+ { method: "POST", body: JSON.stringify(body) }
1810
+ );
1811
+ if (!response.ok) {
1812
+ const data = await response.json();
1813
+ throw new Error(data.error || "Stream request failed");
1814
+ }
1815
+ if (!response.body) {
1816
+ throw new Error("Response body is null");
1817
+ }
1818
+ yield* parseNamedSSEStream(response.body);
1819
+ }
1820
+ /** Cancel the active turn on a session. */
1821
+ async cancelTurn(sessionKey, reason) {
1822
+ const response = await this.httpClient.fetch(
1823
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}/cancel`,
1824
+ {
1825
+ method: "POST",
1826
+ body: reason ? JSON.stringify({ reason }) : void 0
1827
+ }
1828
+ );
1829
+ await parseJsonResponse(response, "Failed to cancel turn");
1830
+ }
1831
+ /** Resolve a pending permission request (call while SSE stream is active). */
1832
+ async resolvePermission(sessionKey, decision) {
1833
+ const response = await this.httpClient.fetch(
1834
+ `/sdk/acp/session/${encodeSessionKey(sessionKey)}/permission`,
1835
+ { method: "POST", body: JSON.stringify(decision) }
1836
+ );
1837
+ return parseJsonResponse(response, "Failed to resolve permission");
1838
+ }
1839
+ /** Convenience: create session + first sync chat in one call. */
1840
+ async startChat(message, options) {
1841
+ const session = await this.createSession(options);
1842
+ const chatResponse = await this.chat(session.session_key, message);
1843
+ return { session, response: chatResponse };
1844
+ }
1845
+ };
1846
+ async function* parseNamedSSEStream(body) {
1847
+ const reader = body.getReader();
1848
+ const decoder = new TextDecoder();
1849
+ let buffer = "";
1850
+ let currentEvent = "";
1851
+ try {
1852
+ while (true) {
1853
+ const { done, value } = await reader.read();
1854
+ if (done) break;
1855
+ buffer += decoder.decode(value, { stream: true });
1856
+ const lines = buffer.split("\n");
1857
+ buffer = lines.pop() || "";
1858
+ for (const line of lines) {
1859
+ if (line.startsWith("event: ")) {
1860
+ currentEvent = line.slice(7).trim();
1861
+ } else if (line.startsWith("data: ")) {
1862
+ const jsonStr = line.slice(6);
1863
+ const eventType = currentEvent || void 0;
1864
+ currentEvent = "";
1865
+ if (!eventType) continue;
1866
+ try {
1867
+ const data = JSON.parse(jsonStr);
1868
+ yield { type: eventType, data };
1869
+ } catch {
1870
+ }
1871
+ } else if (line === "") {
1872
+ currentEvent = "";
1873
+ }
1874
+ }
1875
+ }
1876
+ } finally {
1877
+ reader.releaseLock();
1878
+ }
1879
+ }
1880
+
1611
1881
  // src/modules/mcp.ts
1612
1882
  var MCPModule = class extends ApiModule {
1613
1883
  constructor(realtimexUrl, appId, appName, apiKey) {
@@ -2405,6 +2675,7 @@ var ContractRuntime = class {
2405
2675
  tool_call_id: call.tool_call_id,
2406
2676
  args: call.args,
2407
2677
  context: {
2678
+ app_id: context.appId,
2408
2679
  user_id: context.userId,
2409
2680
  workspace_id: context.workspaceId || null,
2410
2681
  request_id: context.requestId || null,
@@ -2417,7 +2688,9 @@ var ContractRuntime = class {
2417
2688
  }
2418
2689
  return {
2419
2690
  app_name: this.appName,
2420
- app_id: this.appId || context.appId,
2691
+ // In API-key dev mode, app_id should be omitted unless explicitly configured
2692
+ // on the runtime. Passing an unknown app_id causes webhook trigger rejection.
2693
+ app_id: this.appId || void 0,
2421
2694
  event: tool.trigger.event,
2422
2695
  event_id: eventId,
2423
2696
  payload
@@ -3328,6 +3601,7 @@ var _RealtimeXSDK = class _RealtimeXSDK {
3328
3601
  this.tts = new TTSModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
3329
3602
  this.stt = new STTModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
3330
3603
  this.agent = new AgentModule(this.httpClient);
3604
+ this.acpAgent = new AcpAgentModule(this.httpClient);
3331
3605
  this.mcp = new MCPModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
3332
3606
  this.contract = new ContractModule(this.realtimexUrl, this.appName, this.appId, this.apiKey);
3333
3607
  this.contractRuntime = new ContractRuntime({
@@ -3443,6 +3717,7 @@ export {
3443
3717
  ACPEventMapper,
3444
3718
  ACPPermissionBridge,
3445
3719
  ACPTelemetry,
3720
+ AcpAgentModule,
3446
3721
  ActivitiesModule,
3447
3722
  AgentModule,
3448
3723
  ApiModule,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@realtimex/sdk",
3
- "version": "1.3.6",
3
+ "version": "1.4.0",
4
4
  "description": "SDK for building Local Apps that integrate with RealtimeX",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",