@finalai/agents 0.10.0 → 0.12.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.
Files changed (185) hide show
  1. package/HOSTING.md +334 -245
  2. package/README.md +214 -29
  3. package/dist/modules/agent-client/agent-input.d.mts +24 -0
  4. package/dist/modules/agent-client/agent-input.mjs +46 -0
  5. package/dist/modules/agent-client/agent-input.mjs.map +7 -0
  6. package/dist/modules/agent-client/channels.d.mts +52 -3
  7. package/dist/modules/agent-client/channels.mjs +71 -10
  8. package/dist/modules/agent-client/channels.mjs.map +2 -2
  9. package/dist/modules/agent-client/client.d.mts +85 -20
  10. package/dist/modules/agent-client/client.mjs +74 -21
  11. package/dist/modules/agent-client/client.mjs.map +2 -2
  12. package/dist/modules/agent-client/config-options.mjs +1 -2
  13. package/dist/modules/agent-client/config-options.mjs.map +2 -2
  14. package/dist/modules/agent-client/conversation-resources.d.mts +85 -0
  15. package/dist/modules/agent-client/conversation-resources.mjs +150 -0
  16. package/dist/modules/agent-client/conversation-resources.mjs.map +7 -0
  17. package/dist/modules/agent-client/conversations.d.mts +116 -38
  18. package/dist/modules/agent-client/conversations.mjs +379 -71
  19. package/dist/modules/agent-client/conversations.mjs.map +2 -2
  20. package/dist/modules/agent-client/defaults.d.mts +8 -0
  21. package/dist/modules/agent-client/defaults.mjs +77 -0
  22. package/dist/modules/agent-client/defaults.mjs.map +7 -0
  23. package/dist/modules/agent-client/errors.d.mts +22 -2
  24. package/dist/modules/agent-client/errors.mjs +19 -0
  25. package/dist/modules/agent-client/errors.mjs.map +2 -2
  26. package/dist/modules/agent-client/events.d.mts +62 -0
  27. package/dist/modules/agent-client/events.mjs +107 -0
  28. package/dist/modules/agent-client/events.mjs.map +7 -0
  29. package/dist/modules/agent-client/harnesses.d.mts +66 -0
  30. package/dist/modules/agent-client/harnesses.mjs +156 -0
  31. package/dist/modules/agent-client/harnesses.mjs.map +7 -0
  32. package/dist/modules/agent-client/http.d.mts +2 -1
  33. package/dist/modules/agent-client/http.mjs +21 -2
  34. package/dist/modules/agent-client/http.mjs.map +2 -2
  35. package/dist/modules/agent-client/index.d.mts +21 -6
  36. package/dist/modules/agent-client/index.mjs +26 -0
  37. package/dist/modules/agent-client/index.mjs.map +2 -2
  38. package/dist/modules/agent-client/integrations.d.mts +40 -0
  39. package/dist/modules/agent-client/integrations.mjs +92 -0
  40. package/dist/modules/agent-client/integrations.mjs.map +7 -0
  41. package/dist/modules/agent-client/local-host-protocol.d.mts +156 -0
  42. package/dist/modules/agent-client/local-host-protocol.mjs +258 -0
  43. package/dist/modules/agent-client/local-host-protocol.mjs.map +7 -0
  44. package/dist/modules/agent-client/local-host.d.mts +56 -0
  45. package/dist/modules/agent-client/local-host.mjs +200 -0
  46. package/dist/modules/agent-client/local-host.mjs.map +7 -0
  47. package/dist/modules/agent-client/oauth-clients.d.mts +36 -0
  48. package/dist/modules/agent-client/oauth-clients.mjs +67 -0
  49. package/dist/modules/agent-client/oauth-clients.mjs.map +7 -0
  50. package/dist/modules/agent-client/project-agents.d.mts +54 -0
  51. package/dist/modules/agent-client/project-agents.mjs +111 -0
  52. package/dist/modules/agent-client/project-agents.mjs.map +7 -0
  53. package/dist/modules/agent-client/project.d.mts +43 -0
  54. package/dist/modules/agent-client/project.mjs +66 -0
  55. package/dist/modules/agent-client/project.mjs.map +7 -0
  56. package/dist/modules/agent-client/projects.d.mts +61 -0
  57. package/dist/modules/agent-client/projects.mjs +145 -0
  58. package/dist/modules/agent-client/projects.mjs.map +7 -0
  59. package/dist/modules/agent-client/provide.d.mts +41 -0
  60. package/dist/modules/agent-client/provide.mjs +90 -0
  61. package/dist/modules/agent-client/provide.mjs.map +7 -0
  62. package/dist/modules/agent-client/publishers.d.mts +57 -0
  63. package/dist/modules/agent-client/publishers.mjs +109 -0
  64. package/dist/modules/agent-client/publishers.mjs.map +7 -0
  65. package/dist/modules/agent-client/requirements.d.mts +60 -0
  66. package/dist/modules/agent-client/requirements.mjs +83 -0
  67. package/dist/modules/agent-client/requirements.mjs.map +7 -0
  68. package/dist/modules/agent-client/sandbox-providers.d.mts +34 -0
  69. package/dist/modules/agent-client/sandbox-providers.mjs +75 -0
  70. package/dist/modules/agent-client/sandbox-providers.mjs.map +7 -0
  71. package/dist/modules/agent-client/sandbox-uri.d.mts +1 -1
  72. package/dist/modules/agent-client/sandbox-uri.mjs +4 -4
  73. package/dist/modules/agent-client/sandbox-uri.mjs.map +1 -1
  74. package/dist/modules/agent-client/sandboxes.d.mts +65 -0
  75. package/dist/modules/agent-client/sandboxes.mjs +130 -0
  76. package/dist/modules/agent-client/sandboxes.mjs.map +7 -0
  77. package/dist/modules/agent-client/schedules.d.mts +24 -0
  78. package/dist/modules/agent-client/schedules.mjs +56 -0
  79. package/dist/modules/agent-client/schedules.mjs.map +7 -0
  80. package/dist/modules/agent-client/sessions.d.mts +46 -8
  81. package/dist/modules/agent-client/sessions.mjs +91 -29
  82. package/dist/modules/agent-client/sessions.mjs.map +2 -2
  83. package/dist/modules/agent-client/start.d.mts +101 -0
  84. package/dist/modules/agent-client/start.mjs +260 -0
  85. package/dist/modules/agent-client/start.mjs.map +7 -0
  86. package/dist/modules/agent-client/test-fakes.d.mts +1 -0
  87. package/dist/modules/agent-client/test-fakes.mjs +3 -1
  88. package/dist/modules/agent-client/test-fakes.mjs.map +2 -2
  89. package/dist/modules/cli/agent-module.d.mts +39 -0
  90. package/dist/modules/cli/agent-module.mjs +89 -0
  91. package/dist/modules/cli/agent-module.mjs.map +7 -0
  92. package/dist/modules/cli/cli.d.mts +6 -6
  93. package/dist/modules/cli/cli.mjs +94 -120
  94. package/dist/modules/cli/cli.mjs.map +2 -2
  95. package/dist/modules/cli/conformance.d.mts +2 -6
  96. package/dist/modules/cli/conformance.mjs +5 -8
  97. package/dist/modules/cli/conformance.mjs.map +2 -2
  98. package/dist/modules/cli/main.mjs.map +1 -1
  99. package/dist/modules/cli/output.d.mts +0 -9
  100. package/dist/modules/cli/output.mjs +7 -85
  101. package/dist/modules/cli/output.mjs.map +2 -2
  102. package/dist/modules/harnesses.mjs.map +2 -2
  103. package/dist/modules/index.d.mts +0 -2
  104. package/dist/modules/index.mjs +0 -4
  105. package/dist/modules/index.mjs.map +2 -2
  106. package/dist/modules/integrations.d.mts +24 -0
  107. package/dist/modules/integrations.mjs +30 -0
  108. package/dist/modules/integrations.mjs.map +7 -0
  109. package/dist/modules/public.d.mts +10 -10
  110. package/dist/modules/public.mjs +29 -78
  111. package/dist/modules/public.mjs.map +2 -2
  112. package/dist/modules/sandboxes.d.mts +2 -0
  113. package/dist/modules/sandboxes.mjs +4 -0
  114. package/dist/modules/sandboxes.mjs.map +2 -2
  115. package/dist/modules/verify.d.mts +1 -0
  116. package/dist/modules/verify.mjs +2 -0
  117. package/dist/modules/verify.mjs.map +7 -0
  118. package/dist/modules/webhooks.d.mts +37 -0
  119. package/dist/modules/webhooks.mjs +100 -0
  120. package/dist/modules/webhooks.mjs.map +7 -0
  121. package/examples/release-scout/README.md +18 -10
  122. package/examples/release-scout/agent.ts +41 -0
  123. package/examples/release-scout/by-name.ts +43 -0
  124. package/examples/release-scout/db.ts +6 -0
  125. package/examples/release-scout/instructions.md +5 -0
  126. package/examples/release-scout/run-on-a-computer.ts +49 -0
  127. package/examples/release-scout/run.ts +38 -0
  128. package/package.json +42 -28
  129. package/dist/modules/agent-client/build.d.mts +0 -110
  130. package/dist/modules/agent-client/build.mjs +0 -213
  131. package/dist/modules/agent-client/build.mjs.map +0 -7
  132. package/dist/modules/authoring/index.d.mts +0 -1
  133. package/dist/modules/authoring/index.mjs +0 -2
  134. package/dist/modules/authoring/index.mjs.map +0 -7
  135. package/dist/modules/authoring/instructions.d.mts +0 -1
  136. package/dist/modules/authoring/instructions.mjs +0 -2
  137. package/dist/modules/authoring/instructions.mjs.map +0 -7
  138. package/dist/modules/authoring/providers.d.mts +0 -2
  139. package/dist/modules/authoring/providers.mjs +0 -1
  140. package/dist/modules/authoring/providers.mjs.map +0 -7
  141. package/dist/modules/cli/build.d.mts +0 -22
  142. package/dist/modules/cli/build.mjs +0 -77
  143. package/dist/modules/cli/build.mjs.map +0 -7
  144. package/dist/modules/cli/channel-install.d.mts +0 -12
  145. package/dist/modules/cli/channel-install.mjs +0 -25
  146. package/dist/modules/cli/channel-install.mjs.map +0 -7
  147. package/dist/modules/cli/channel-socket.d.mts +0 -9
  148. package/dist/modules/cli/channel-socket.mjs +0 -114
  149. package/dist/modules/cli/channel-socket.mjs.map +0 -7
  150. package/dist/modules/cli/dev.d.mts +0 -26
  151. package/dist/modules/cli/dev.mjs +0 -311
  152. package/dist/modules/cli/dev.mjs.map +0 -7
  153. package/dist/modules/cli/files.d.mts +0 -18
  154. package/dist/modules/cli/files.mjs +0 -66
  155. package/dist/modules/cli/files.mjs.map +0 -7
  156. package/dist/modules/cli/harness-descriptions.d.mts +0 -20
  157. package/dist/modules/cli/harness-descriptions.mjs +0 -70
  158. package/dist/modules/cli/harness-descriptions.mjs.map +0 -7
  159. package/dist/modules/cli/publish.d.mts +0 -15
  160. package/dist/modules/cli/publish.mjs +0 -92
  161. package/dist/modules/cli/publish.mjs.map +0 -7
  162. package/dist/modules/compile.d.mts +0 -3
  163. package/dist/modules/compile.mjs +0 -58
  164. package/dist/modules/compile.mjs.map +0 -7
  165. package/dist/modules/index.browser.d.mts +0 -4
  166. package/dist/modules/index.browser.mjs +0 -8
  167. package/dist/modules/index.browser.mjs.map +0 -7
  168. package/examples/custom-harness/README.md +0 -16
  169. package/examples/custom-harness/agent.ts +0 -154
  170. package/examples/custom-sandbox/README.md +0 -12
  171. package/examples/custom-sandbox/agent.ts +0 -14
  172. package/examples/custom-sandbox/sandbox.ts +0 -24
  173. package/examples/release-scout/agent/agent.ts +0 -22
  174. package/examples/release-scout/agent/channels/github-signature.ts +0 -27
  175. package/examples/release-scout/agent/channels/github.ts +0 -32
  176. package/examples/release-scout/agent/connections/linear.ts +0 -9
  177. package/examples/release-scout/agent/hooks/audit.ts +0 -24
  178. package/examples/release-scout/agent/instructions/org-context.ts +0 -26
  179. package/examples/release-scout/agent/instructions.md +0 -2
  180. package/examples/release-scout/agent/sandbox.ts +0 -20
  181. package/examples/release-scout/agent/schedules/daily-digest.md +0 -7
  182. package/examples/release-scout/agent/skills/triage/SKILL.md +0 -8
  183. package/examples/release-scout/agent/skills/triage/checklist.md +0 -3
  184. package/examples/release-scout/agent/tools/lookup_release_notes.ts +0 -24
  185. package/examples/release-scout/client.ts +0 -122
@@ -1,20 +1,36 @@
1
- import { type AgentInfoIface, type AgentListIface, type HealthResponseIface, type PersonIface, type PersonListIface, type RealtimeSessionResponseIface } from '@finalai/agent-protocol/agent-platform';
1
+ import { type AgentListIface, type DecisionIface, type HealthResponseIface, type InferenceOfferingIface, type PersonIface, type PersonListIface, type PlatformIdentityExchangeRequestIface, type PlatformIdentityExchangeResponseIface, type RealtimeSessionResponseIface } from '@finalai/agent-protocol/agent-platform';
2
2
  import { type AcpApiIface } from "./acp.mjs";
3
- import { type ComputerSetupGuidesApiIface, type DefinitionsApiIface, type ProvidersApiIface, type SchedulesApiIface } from "./build.mjs";
3
+ import type { AgentValueCodecIface } from "./agent-input.mjs";
4
+ import { type ChannelBindingsApiIface, type ChannelSourceOf } from "./channels.mjs";
4
5
  import { type SignalOptionsIface } from "./context.mjs";
5
- import { type ChannelBindingsApiIface } from "./channels.mjs";
6
6
  import { type ConversationsApiIface } from "./conversations.mjs";
7
+ import { type EventsApiIface, type EventSubscriptionsApiIface } from "./events.mjs";
7
8
  import { type StreamTimingIface } from "./frame-stream.mjs";
8
9
  import { type AgentClientAuth, type FetchIface, type HeadersOption } from "./http.mjs";
9
10
  import { type GatewayConnect, type RealtimeTransportIface } from "./realtime.mjs";
11
+ import type { LocalComputeIface, LocalHostSocketIface } from "./local-host.mjs";
12
+ import { type ProjectClientIface } from "./project.mjs";
13
+ import { type ProjectsApiIface } from "./projects.mjs";
14
+ import { type PublishersApiIface } from "./publishers.mjs";
15
+ import { type SchedulesApiIface } from "./schedules.mjs";
10
16
  import { type SessionsApiIface } from "./sessions.mjs";
17
+ /** Final's agents API. */
18
+ export declare const DEFAULT_AGENTS_HOST = "https://agent-session.final.ai";
11
19
  export interface CreateClientOptionsIface {
20
+ auth: AgentClientAuth;
12
21
  /**
13
- * The agents API origin (`https://agent-session.final.ai`; its API is under
14
- * `/api` and ACP at `/acp/ws`), or a base URL the API routes are mounted under.
22
+ * Whether this process provides the files and shell an agent requires when
23
+ * the caller leaves them out (default true), so the model's file edits and
24
+ * commands run here, on this machine. A server should provide every
25
+ * capability explicitly and pass false, so an omission fails with
26
+ * `requirements_unmet` instead of giving the model a shell in the server.
15
27
  */
16
- host: string;
17
- auth: AgentClientAuth;
28
+ localCompute?: boolean;
29
+ /**
30
+ * The agents API origin (default `https://agent-session.final.ai`; its API is
31
+ * under `/api` and ACP at `/acp/ws`), or a base URL the API routes are mounted under.
32
+ */
33
+ host?: string;
18
34
  /** Extra headers per request; console clients send their client identity header here. */
19
35
  headers?: HeadersOption;
20
36
  /** API requests (the host's routes); carries auth and caller headers. */
@@ -36,24 +52,29 @@ export interface CreateClientOptionsIface {
36
52
  newKey?: () => string;
37
53
  /** Seam for the client clock (conversation recovery windows). */
38
54
  now?: () => number;
39
- }
40
- export interface AgentHandleIface {
41
- slug: string;
42
- info: (options?: SignalOptionsIface) => Promise<AgentInfoIface>;
55
+ /** Seam: how agent values become documents and in-process code. */
56
+ agentCodec?: AgentValueCodecIface;
57
+ /** Seam: how a channel value becomes its source. */
58
+ channelSourceOf?: ChannelSourceOf;
59
+ /** Seams for local hosts: the socket, and the sandbox this process serves. */
60
+ localHosts?: {
61
+ /** Opens the local host socket; abandons it when `signal` aborts. */
62
+ dial?: (path: string, signal?: AbortSignal) => Promise<LocalHostSocketIface>;
63
+ compute?: Partial<LocalComputeIface>;
64
+ };
43
65
  }
44
66
  export interface AgentsApiIface {
45
67
  /**
46
68
  * The agents the caller can use; with `projectId`, those usable there (its own and those
47
69
  * inherited from its ancestors). Without it, everything the caller can access (an API key: its
48
70
  * parent project and every project it is granted; a person: every project they can read).
71
+ * Fetch one as data with `client.project({ id }).agents.get`.
49
72
  */
50
73
  list: (options?: SignalOptionsIface & {
51
74
  cursor?: string;
52
75
  limit?: number;
53
76
  projectId?: string;
54
77
  }) => Promise<AgentListIface>;
55
- /** I/O-free handle by slug or id. */
56
- get: (slugOrId: string) => AgentHandleIface;
57
78
  }
58
79
  export interface PeopleApiIface {
59
80
  /** One page of the caller's organization members, by name; pass `nextCursor` as `cursor` for the next. */
@@ -72,17 +93,59 @@ export interface RealtimeApiIface {
72
93
  */
73
94
  createSession: (options?: SignalOptionsIface) => Promise<RealtimeSessionResponseIface>;
74
95
  }
96
+ export interface InferenceApiIface {
97
+ /**
98
+ * The vendors and models the platform's own metered inference serves, with
99
+ * prices (`GET /v1/inference/offering`, public). A harness using the
100
+ * platform's inference can run only models listed here.
101
+ */
102
+ offering: (options?: SignalOptionsIface) => Promise<InferenceOfferingIface>;
103
+ }
104
+ export interface PlatformIdentityApiIface {
105
+ /**
106
+ * Exchanges a sandbox-provider (or downstream) assertion the platform issued
107
+ * for a fresh one: for the provider's own URL (a refresh) or a backend its
108
+ * registration was granted. The subject token is the credential.
109
+ */
110
+ exchange: (args: PlatformIdentityExchangeRequestIface & SignalOptionsIface) => Promise<PlatformIdentityExchangeResponseIface>;
111
+ }
112
+ export interface DecisionsApiIface {
113
+ /** One decision awaiting the caller's answer, as `conversations.decisions` lists it. */
114
+ get: (args: {
115
+ id: string;
116
+ } & SignalOptionsIface) => Promise<DecisionIface>;
117
+ }
118
+ export interface AppApiIface {
119
+ /**
120
+ * The calling app's event subscriptions, across every organization that
121
+ * installed it. Needs an app-level token.
122
+ */
123
+ eventSubscriptions: EventSubscriptionsApiIface;
124
+ }
75
125
  export interface AgentClientIface {
126
+ /** One project: where sessions, conversations, sandboxes and integrations are created. */
127
+ project: (args: {
128
+ id: string;
129
+ }) => ProjectClientIface;
130
+ /** The project tree: list projects and create them. */
131
+ projects: ProjectsApiIface;
132
+ /** The event feed across everything the caller can see; `project({ id }).events` narrows it. */
133
+ events: EventsApiIface;
134
+ app: AppApiIface;
135
+ /** Publishers' public agents, channels, harnesses and ACP adapters. */
136
+ publishers: PublishersApiIface;
137
+ inference: InferenceApiIface;
138
+ platformIdentity: PlatformIdentityApiIface;
139
+ decisions: DecisionsApiIface;
76
140
  health: (options?: SignalOptionsIface) => Promise<HealthResponseIface>;
77
141
  agents: AgentsApiIface;
78
142
  people: PeopleApiIface;
79
143
  realtime: RealtimeApiIface;
144
+ /** Existing sessions by id; create them through `project({ id }).sessions`. */
80
145
  sessions: SessionsApiIface;
146
+ /** The caller's conversations; create them through `project({ id }).conversations`. */
81
147
  conversations: ConversationsApiIface;
82
148
  channelBindings: ChannelBindingsApiIface;
83
- definitions: DefinitionsApiIface;
84
- providers: ProvidersApiIface;
85
- computerSetupGuides: ComputerSetupGuidesApiIface;
86
149
  schedules: SchedulesApiIface;
87
150
  /**
88
151
  * ACP-native access (`/acp/ws`): an ACP v2 ClientApp connection on which the
@@ -90,10 +153,12 @@ export interface AgentClientIface {
90
153
  */
91
154
  acp: AcpApiIface;
92
155
  /**
93
- * Ends every stream (they reject with a `client_closed` ClientError) and, when
94
- * the client created its own realtime transport, closes the gateway connection
95
- * and cancels its retries. A transport passed in `realtime` belongs to the
96
- * caller and is left open. Idempotent.
156
+ * Ends every stream (they reject with a `client_closed` ClientError) and every
157
+ * local host connection (the platform then reports this process's tools and
158
+ * compute as unavailable; sessions carry on) and, when the client created its
159
+ * own realtime transport, closes the gateway connection and cancels its
160
+ * retries. A transport passed in `realtime` belongs to the caller and is left
161
+ * open. Idempotent.
97
162
  */
98
163
  close: () => void;
99
164
  [Symbol.asyncDispose]: () => Promise<void>;
@@ -1,22 +1,31 @@
1
1
  import {
2
- agentInfoSchema,
3
2
  agentListSchema,
4
3
  agentRealtimeTopics,
4
+ decisionResponseSchema,
5
5
  healthResponseSchema,
6
+ inferenceOfferingSchema,
6
7
  personListSchema,
8
+ platformIdentityExchangeRequestSchema,
9
+ platformIdentityExchangeResponseSchema,
7
10
  realtimeSessionResponseSchema
8
11
  } from "@finalai/agent-protocol/agent-platform";
9
12
  import { createAcpApi } from "./acp.mjs";
10
13
  import {
11
- createComputerSetupGuidesApi,
12
- createDefinitionsApi,
13
- createProvidersApi,
14
- createSchedulesApi
15
- } from "./build.mjs";
14
+ createChannelBindingsApi
15
+ } from "./channels.mjs";
16
16
  import { encodePath } from "./context.mjs";
17
- import { createChannelBindingsApi } from "./channels.mjs";
18
17
  import { createConversationsApi } from "./conversations.mjs";
18
+ import {
19
+ defaultAgentCodec,
20
+ defaultChannelSourceOf,
21
+ defaultLocalCompute,
22
+ defaultLocalHostDial
23
+ } from "./defaults.mjs";
19
24
  import { clientError, ClientErrorCode } from "./errors.mjs";
25
+ import {
26
+ createEventsApi,
27
+ createEventSubscriptionsApi
28
+ } from "./events.mjs";
20
29
  import { defaultStreamTiming } from "./frame-stream.mjs";
21
30
  import {
22
31
  createHttp,
@@ -25,10 +34,15 @@ import {
25
34
  import {
26
35
  createGatewayRealtimeTransport
27
36
  } from "./realtime.mjs";
37
+ import { createProjectClient } from "./project.mjs";
38
+ import { createProjectsApi } from "./projects.mjs";
39
+ import { createPublishersApi } from "./publishers.mjs";
40
+ import { createSchedulesApi } from "./schedules.mjs";
28
41
  import { createSessionsApi } from "./sessions.mjs";
42
+ const DEFAULT_AGENTS_HOST = "https://agent-session.final.ai";
29
43
  const createClient = (options) => {
30
44
  const http = createHttp({
31
- host: options.host,
45
+ host: options.host ?? DEFAULT_AGENTS_HOST,
32
46
  auth: options.auth,
33
47
  headers: options.headers,
34
48
  fetch: options.fetch
@@ -92,11 +106,25 @@ const createClient = (options) => {
92
106
  newKey: options.newKey ?? (() => globalThis.crypto.randomUUID()),
93
107
  now: options.now ?? Date.now
94
108
  };
109
+ const hosts = /* @__PURE__ */ new Set();
110
+ const localCompute = defaultLocalCompute();
111
+ const start = {
112
+ context,
113
+ codec: options.agentCodec ?? defaultAgentCodec,
114
+ localCompute: options.localCompute ?? true,
115
+ compute: { ...localCompute, ...options.localHosts?.compute },
116
+ dial: options.localHosts?.dial ?? defaultLocalHostDial(http),
117
+ hosts
118
+ };
119
+ const channelSourceOf = options.channelSourceOf ?? defaultChannelSourceOf;
120
+ const clientLevel = { deps: start, projectId: null };
95
121
  const close = () => {
96
122
  if (closing.signal.aborted) return;
97
123
  closing.abort(
98
124
  clientError({ message: "Agent client closed", status: 0, code: ClientErrorCode.Closed })
99
125
  );
126
+ for (const host of hosts) host.close();
127
+ hosts.clear();
100
128
  ownTransport?.close();
101
129
  };
102
130
  return {
@@ -119,15 +147,6 @@ const createClient = (options) => {
119
147
  },
120
148
  response: agentListSchema,
121
149
  signal: listOptions?.signal
122
- }),
123
- get: (slugOrId) => ({
124
- slug: slugOrId,
125
- info: (infoOptions) => http.request({
126
- method: HttpMethod.Get,
127
- path: `/v1/agents/${encodePath(slugOrId)}`,
128
- response: agentInfoSchema,
129
- signal: infoOptions?.signal
130
- })
131
150
  })
132
151
  },
133
152
  people: /* @__PURE__ */ (() => {
@@ -153,17 +172,51 @@ const createClient = (options) => {
153
172
  };
154
173
  })(),
155
174
  realtime: { createSession: createRealtimeSession },
175
+ project: ({ id }) => createProjectClient({ context, start, channelSourceOf, projectId: id }),
176
+ projects: createProjectsApi(context),
177
+ events: createEventsApi({ context, projectId: null }),
178
+ app: {
179
+ eventSubscriptions: createEventSubscriptionsApi({
180
+ context,
181
+ basePath: "/v1/apps/me/event-subscriptions"
182
+ })
183
+ },
184
+ publishers: createPublishersApi(context),
185
+ inference: {
186
+ offering: (offeringOptions) => http.request({
187
+ method: HttpMethod.Get,
188
+ path: "/v1/inference/offering",
189
+ response: inferenceOfferingSchema,
190
+ signal: offeringOptions?.signal
191
+ })
192
+ },
193
+ platformIdentity: {
194
+ exchange: ({ signal, ...value }) => http.request({
195
+ method: HttpMethod.Post,
196
+ path: "/v1/platform-identity/exchange",
197
+ body: { schema: platformIdentityExchangeRequestSchema, value },
198
+ response: platformIdentityExchangeResponseSchema,
199
+ signal
200
+ })
201
+ },
202
+ decisions: {
203
+ get: async ({ id, signal }) => (await http.request({
204
+ method: HttpMethod.Get,
205
+ path: `/v1/decisions/${encodePath(id)}`,
206
+ response: decisionResponseSchema,
207
+ signal,
208
+ context: { decisionId: id }
209
+ })).decision
210
+ },
156
211
  sessions: createSessionsApi(context),
157
- conversations: createConversationsApi(context),
212
+ conversations: createConversationsApi(context, clientLevel),
158
213
  channelBindings: createChannelBindingsApi(context),
159
- definitions: createDefinitionsApi(context),
160
- providers: createProvidersApi(context),
161
- computerSetupGuides: createComputerSetupGuidesApi(context),
162
214
  schedules: createSchedulesApi(context),
163
215
  acp: createAcpApi({ http })
164
216
  };
165
217
  };
166
218
  export {
219
+ DEFAULT_AGENTS_HOST,
167
220
  createClient
168
221
  };
169
222
  //# sourceMappingURL=client.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/agent-client/client.ts"],
4
- "sourcesContent": ["import {\n agentInfoSchema,\n agentListSchema,\n agentRealtimeTopics,\n healthResponseSchema,\n personListSchema,\n realtimeSessionResponseSchema,\n type AgentInfoIface,\n type AgentListIface,\n type HealthResponseIface,\n type PersonIface,\n type PersonListIface,\n type RealtimeSessionResponseIface,\n} from '@finalai/agent-protocol/agent-platform';\nimport { createAcpApi, type AcpApiIface } from \"./acp.mjs\";\nimport {\n createComputerSetupGuidesApi,\n createDefinitionsApi,\n createProvidersApi,\n createSchedulesApi,\n type ComputerSetupGuidesApiIface,\n type DefinitionsApiIface,\n type ProvidersApiIface,\n type SchedulesApiIface,\n} from \"./build.mjs\";\nimport { encodePath, type ClientContextIface, type SignalOptionsIface } from \"./context.mjs\";\nimport { createChannelBindingsApi, type ChannelBindingsApiIface } from \"./channels.mjs\";\nimport { createConversationsApi, type ConversationsApiIface } from \"./conversations.mjs\";\nimport { clientError, ClientErrorCode } from \"./errors.mjs\";\nimport { defaultStreamTiming, type StreamTimingIface } from \"./frame-stream.mjs\";\nimport {\n createHttp,\n HttpMethod,\n type AgentClientAuth,\n type FetchIface,\n type HeadersOption,\n} from \"./http.mjs\";\nimport {\n createGatewayRealtimeTransport,\n type GatewayConnect,\n type GatewayRealtimeTransportIface,\n type RealtimeTransportIface,\n} from \"./realtime.mjs\";\nimport { createSessionsApi, type SessionsApiIface } from \"./sessions.mjs\";\n\nexport interface CreateClientOptionsIface {\n /**\n * The agents API origin (`https://agent-session.final.ai`; its API is under\n * `/api` and ACP at `/acp/ws`), or a base URL the API routes are mounted under.\n */\n host: string;\n auth: AgentClientAuth;\n /** Extra headers per request; console clients send their client identity header here. */\n headers?: HeadersOption;\n /** API requests (the host's routes); carries auth and caller headers. */\n fetch?: FetchIface;\n /**\n * Presigned storage requests (attachment uploads). Gets only the headers the\n * presign requires, never auth, client identity or cookies, so a storage\n * bucket's CORS and third-party hosts see nothing of the caller. Defaults to\n * `globalThis.fetch`; keep it free of header-injecting wrappers.\n */\n storageFetch?: FetchIface;\n /** console-web and console-mobile pass their realtime clients; defaults to a gateway connection. */\n realtime?: RealtimeTransportIface;\n /** Seam for the default transport's gateway connection. */\n gatewayConnect?: GatewayConnect;\n /** Seam for stream retry timing (tests). */\n timing?: Partial<StreamTimingIface>;\n /** Seam for idempotency keys and client message ids; defaults to `crypto.randomUUID`. */\n newKey?: () => string;\n /** Seam for the client clock (conversation recovery windows). */\n now?: () => number;\n}\n\nexport interface AgentHandleIface {\n slug: string;\n info: (options?: SignalOptionsIface) => Promise<AgentInfoIface>;\n}\n\nexport interface AgentsApiIface {\n /**\n * The agents the caller can use; with `projectId`, those usable there (its own and those\n * inherited from its ancestors). Without it, everything the caller can access (an API key: its\n * parent project and every project it is granted; a person: every project they can read).\n */\n list: (\n options?: SignalOptionsIface & { cursor?: string; limit?: number; projectId?: string },\n ) => Promise<AgentListIface>;\n /** I/O-free handle by slug or id. */\n get: (slugOrId: string) => AgentHandleIface;\n}\n\nexport interface PeopleApiIface {\n /** One page of the caller's organization members, by name; pass `nextCursor` as `cursor` for the next. */\n list: (\n options?: SignalOptionsIface & { cursor?: string; limit?: number },\n ) => Promise<PersonListIface>;\n /** Every member of the caller's organization (all pages). */\n all: (options?: SignalOptionsIface) => Promise<PersonIface[]>;\n}\n\nexport interface RealtimeApiIface {\n /**\n * Mints a gateway session (`POST /v1/realtime/session`) for the signed-in user:\n * the gateway URL, a short-lived token, and the user id realtime topics are keyed by.\n * Pass it as `createSession` to `createGatewayRealtimeTransport` when supplying a transport.\n */\n createSession: (options?: SignalOptionsIface) => Promise<RealtimeSessionResponseIface>;\n}\n\nexport interface AgentClientIface {\n health: (options?: SignalOptionsIface) => Promise<HealthResponseIface>;\n agents: AgentsApiIface;\n people: PeopleApiIface;\n realtime: RealtimeApiIface;\n sessions: SessionsApiIface;\n conversations: ConversationsApiIface;\n channelBindings: ChannelBindingsApiIface;\n definitions: DefinitionsApiIface;\n providers: ProvidersApiIface;\n computerSetupGuides: ComputerSetupGuidesApiIface;\n schedules: SchedulesApiIface;\n /**\n * ACP-native access (`/acp/ws`): an ACP v2 ClientApp connection on which the\n * agents API is the agent. The ACP SDK loads on the first `connect`.\n */\n acp: AcpApiIface;\n /**\n * Ends every stream (they reject with a `client_closed` ClientError) and, when\n * the client created its own realtime transport, closes the gateway connection\n * and cancels its retries. A transport passed in `realtime` belongs to the\n * caller and is left open. Idempotent.\n */\n close: () => void;\n [Symbol.asyncDispose]: () => Promise<void>;\n}\n\nexport const createClient = (options: CreateClientOptionsIface): AgentClientIface => {\n const http = createHttp({\n host: options.host,\n auth: options.auth,\n headers: options.headers,\n fetch: options.fetch,\n });\n let realtime = options.realtime ?? null;\n let ownTransport: GatewayRealtimeTransportIface | null = null;\n const closing = new AbortController();\n const createRealtimeSession: RealtimeApiIface['createSession'] = (sessionOptions) =>\n http.request({\n method: HttpMethod.Post,\n path: '/v1/realtime/session',\n response: realtimeSessionResponseSchema,\n signal: sessionOptions?.signal,\n });\n let realtimeOwner: Promise<RealtimeSessionResponseIface> | null = null;\n const realtimeOwnerSession = () => {\n if (realtimeOwner != null) return realtimeOwner;\n const pending = createRealtimeSession({ signal: closing.signal });\n realtimeOwner = pending;\n void pending.catch(() => {\n if (realtimeOwner === pending) realtimeOwner = null;\n });\n return pending;\n };\n let realtimeUser: Promise<string> | null = null;\n // Shared by every stream, so it is cancelled only with the client, never by one caller.\n const realtimeUserId: ClientContextIface['realtimeUserId'] = () => {\n if (realtimeUser != null) return realtimeUser;\n const pending = realtimeOwnerSession().then((session) => {\n if (session.userId == null)\n throw new Error('This client authenticates as an API-key owner, not a user');\n return session.userId;\n });\n realtimeUser = pending;\n // A failed (or aborted) read is not cached.\n pending.catch(() => {\n if (realtimeUser === pending) realtimeUser = null;\n });\n return pending;\n };\n const context: ClientContextIface = {\n http,\n closeSignal: closing.signal,\n realtimeUserId,\n // Conversations is the only collection.\n realtimeCollectionTopic: async () => {\n const owner = await realtimeOwnerSession();\n // API keys act in their project, not as members: they reach agents through channels.\n if (owner.userId == null)\n throw new Error('Collection streams belong to users; API-key owners use session streams');\n return agentRealtimeTopics.userConversations(owner.userId);\n },\n storageFetch: options.storageFetch ?? ((input, init) => globalThis.fetch(input, init)),\n realtime: () => {\n if (realtime != null) return realtime;\n ownTransport = createGatewayRealtimeTransport({\n createSession: () => createRealtimeSession(),\n connect: options.gatewayConnect,\n });\n if (closing.signal.aborted) ownTransport.close();\n realtime = ownTransport;\n return realtime;\n },\n timing: { ...defaultStreamTiming, ...options.timing },\n newKey: options.newKey ?? (() => globalThis.crypto.randomUUID()),\n now: options.now ?? Date.now,\n };\n\n const close = (): void => {\n if (closing.signal.aborted) return;\n closing.abort(\n clientError({ message: 'Agent client closed', status: 0, code: ClientErrorCode.Closed }),\n );\n ownTransport?.close();\n };\n\n return {\n close,\n [Symbol.asyncDispose]: async () => close(),\n health: (healthOptions) =>\n http.request({\n method: HttpMethod.Get,\n path: '/v1/health',\n response: healthResponseSchema,\n signal: healthOptions?.signal,\n }),\n agents: {\n list: (listOptions) =>\n http.request({\n method: HttpMethod.Get,\n path: '/v1/agents',\n query: {\n cursor: listOptions?.cursor,\n limit: listOptions?.limit,\n projectId: listOptions?.projectId,\n },\n response: agentListSchema,\n signal: listOptions?.signal,\n }),\n get: (slugOrId) => ({\n slug: slugOrId,\n info: (infoOptions) =>\n http.request({\n method: HttpMethod.Get,\n path: `/v1/agents/${encodePath(slugOrId)}`,\n response: agentInfoSchema,\n signal: infoOptions?.signal,\n }),\n }),\n },\n people: (() => {\n const list: PeopleApiIface['list'] = (listOptions) =>\n http.request({\n method: HttpMethod.Get,\n path: '/v1/people',\n query: { cursor: listOptions?.cursor, limit: listOptions?.limit },\n response: personListSchema,\n signal: listOptions?.signal,\n });\n return {\n list,\n all: async (allOptions) => {\n const all: PersonIface[] = [];\n let cursor: string | undefined;\n for (;;) {\n const next = await list({ cursor, signal: allOptions?.signal });\n all.push(...next.people);\n if (next.nextCursor == null) return all;\n cursor = next.nextCursor;\n }\n },\n };\n })(),\n realtime: { createSession: createRealtimeSession },\n sessions: createSessionsApi(context),\n conversations: createConversationsApi(context),\n channelBindings: createChannelBindingsApi(context),\n definitions: createDefinitionsApi(context),\n providers: createProvidersApi(context),\n computerSetupGuides: createComputerSetupGuidesApi(context),\n schedules: createSchedulesApi(context),\n acp: createAcpApi({ http }),\n };\n};\n"],
5
- "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAOK;AACP,SAAS,oBAAsC;AAC/C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP,SAAS,kBAAoE;AAC7E,SAAS,gCAA8D;AACvE,SAAS,8BAA0D;AACnE,SAAS,aAAa,uBAAuB;AAC7C,SAAS,2BAAmD;AAC5D;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AACP;AAAA,EACE;AAAA,OAIK;AACP,SAAS,yBAAgD;AA+FlD,MAAM,eAAe,CAAC,YAAwD;AACnF,QAAM,OAAO,WAAW;AAAA,IACtB,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,IACjB,OAAO,QAAQ;AAAA,EACjB,CAAC;AACD,MAAI,WAAW,QAAQ,YAAY;AACnC,MAAI,eAAqD;AACzD,QAAM,UAAU,IAAI,gBAAgB;AACpC,QAAM,wBAA2D,CAAC,mBAChE,KAAK,QAAQ;AAAA,IACX,QAAQ,WAAW;AAAA,IACnB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,gBAAgB;AAAA,EAC1B,CAAC;AACH,MAAI,gBAA8D;AAClE,QAAM,uBAAuB,MAAM;AACjC,QAAI,iBAAiB,KAAM,QAAO;AAClC,UAAM,UAAU,sBAAsB,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAChE,oBAAgB;AAChB,SAAK,QAAQ,MAAM,MAAM;AACvB,UAAI,kBAAkB,QAAS,iBAAgB;AAAA,IACjD,CAAC;AACD,WAAO;AAAA,EACT;AACA,MAAI,eAAuC;AAE3C,QAAM,iBAAuD,MAAM;AACjE,QAAI,gBAAgB,KAAM,QAAO;AACjC,UAAM,UAAU,qBAAqB,EAAE,KAAK,CAAC,YAAY;AACvD,UAAI,QAAQ,UAAU;AACpB,cAAM,IAAI,MAAM,2DAA2D;AAC7E,aAAO,QAAQ;AAAA,IACjB,CAAC;AACD,mBAAe;AAEf,YAAQ,MAAM,MAAM;AAClB,UAAI,iBAAiB,QAAS,gBAAe;AAAA,IAC/C,CAAC;AACD,WAAO;AAAA,EACT;AACA,QAAM,UAA8B;AAAA,IAClC;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB;AAAA;AAAA,IAEA,yBAAyB,YAAY;AACnC,YAAM,QAAQ,MAAM,qBAAqB;AAEzC,UAAI,MAAM,UAAU;AAClB,cAAM,IAAI,MAAM,wEAAwE;AAC1F,aAAO,oBAAoB,kBAAkB,MAAM,MAAM;AAAA,IAC3D;AAAA,IACA,cAAc,QAAQ,iBAAiB,CAAC,OAAO,SAAS,WAAW,MAAM,OAAO,IAAI;AAAA,IACpF,UAAU,MAAM;AACd,UAAI,YAAY,KAAM,QAAO;AAC7B,qBAAe,+BAA+B;AAAA,QAC5C,eAAe,MAAM,sBAAsB;AAAA,QAC3C,SAAS,QAAQ;AAAA,MACnB,CAAC;AACD,UAAI,QAAQ,OAAO,QAAS,cAAa,MAAM;AAC/C,iBAAW;AACX,aAAO;AAAA,IACT;AAAA,IACA,QAAQ,EAAE,GAAG,qBAAqB,GAAG,QAAQ,OAAO;AAAA,IACpD,QAAQ,QAAQ,WAAW,MAAM,WAAW,OAAO,WAAW;AAAA,IAC9D,KAAK,QAAQ,OAAO,KAAK;AAAA,EAC3B;AAEA,QAAM,QAAQ,MAAY;AACxB,QAAI,QAAQ,OAAO,QAAS;AAC5B,YAAQ;AAAA,MACN,YAAY,EAAE,SAAS,uBAAuB,QAAQ,GAAG,MAAM,gBAAgB,OAAO,CAAC;AAAA,IACzF;AACA,kBAAc,MAAM;AAAA,EACtB;AAEA,SAAO;AAAA,IACL;AAAA,IACA,CAAC,OAAO,YAAY,GAAG,YAAY,MAAM;AAAA,IACzC,QAAQ,CAAC,kBACP,KAAK,QAAQ;AAAA,MACX,QAAQ,WAAW;AAAA,MACnB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ,eAAe;AAAA,IACzB,CAAC;AAAA,IACH,QAAQ;AAAA,MACN,MAAM,CAAC,gBACL,KAAK,QAAQ;AAAA,QACX,QAAQ,WAAW;AAAA,QACnB,MAAM;AAAA,QACN,OAAO;AAAA,UACL,QAAQ,aAAa;AAAA,UACrB,OAAO,aAAa;AAAA,UACpB,WAAW,aAAa;AAAA,QAC1B;AAAA,QACA,UAAU;AAAA,QACV,QAAQ,aAAa;AAAA,MACvB,CAAC;AAAA,MACH,KAAK,CAAC,cAAc;AAAA,QAClB,MAAM;AAAA,QACN,MAAM,CAAC,gBACL,KAAK,QAAQ;AAAA,UACX,QAAQ,WAAW;AAAA,UACnB,MAAM,cAAc,WAAW,QAAQ,CAAC;AAAA,UACxC,UAAU;AAAA,UACV,QAAQ,aAAa;AAAA,QACvB,CAAC;AAAA,MACL;AAAA,IACF;AAAA,IACA,QAAS,uBAAM;AACb,YAAM,OAA+B,CAAC,gBACpC,KAAK,QAAQ;AAAA,QACX,QAAQ,WAAW;AAAA,QACnB,MAAM;AAAA,QACN,OAAO,EAAE,QAAQ,aAAa,QAAQ,OAAO,aAAa,MAAM;AAAA,QAChE,UAAU;AAAA,QACV,QAAQ,aAAa;AAAA,MACvB,CAAC;AACH,aAAO;AAAA,QACL;AAAA,QACA,KAAK,OAAO,eAAe;AACzB,gBAAM,MAAqB,CAAC;AAC5B,cAAI;AACJ,qBAAS;AACP,kBAAM,OAAO,MAAM,KAAK,EAAE,QAAQ,QAAQ,YAAY,OAAO,CAAC;AAC9D,gBAAI,KAAK,GAAG,KAAK,MAAM;AACvB,gBAAI,KAAK,cAAc,KAAM,QAAO;AACpC,qBAAS,KAAK;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,IACF,GAAG;AAAA,IACH,UAAU,EAAE,eAAe,sBAAsB;AAAA,IACjD,UAAU,kBAAkB,OAAO;AAAA,IACnC,eAAe,uBAAuB,OAAO;AAAA,IAC7C,iBAAiB,yBAAyB,OAAO;AAAA,IACjD,aAAa,qBAAqB,OAAO;AAAA,IACzC,WAAW,mBAAmB,OAAO;AAAA,IACrC,qBAAqB,6BAA6B,OAAO;AAAA,IACzD,WAAW,mBAAmB,OAAO;AAAA,IACrC,KAAK,aAAa,EAAE,KAAK,CAAC;AAAA,EAC5B;AACF;",
4
+ "sourcesContent": ["import {\n agentListSchema,\n agentRealtimeTopics,\n decisionResponseSchema,\n healthResponseSchema,\n inferenceOfferingSchema,\n personListSchema,\n platformIdentityExchangeRequestSchema,\n platformIdentityExchangeResponseSchema,\n realtimeSessionResponseSchema,\n type AgentListIface,\n type DecisionIface,\n type HealthResponseIface,\n type InferenceOfferingIface,\n type PersonIface,\n type PersonListIface,\n type PlatformIdentityExchangeRequestIface,\n type PlatformIdentityExchangeResponseIface,\n type RealtimeSessionResponseIface,\n} from '@finalai/agent-protocol/agent-platform';\nimport { createAcpApi, type AcpApiIface } from \"./acp.mjs\";\nimport type { AgentValueCodecIface } from \"./agent-input.mjs\";\nimport {\n createChannelBindingsApi,\n type ChannelBindingsApiIface,\n type ChannelSourceOf,\n} from \"./channels.mjs\";\nimport { encodePath, type ClientContextIface, type SignalOptionsIface } from \"./context.mjs\";\nimport { createConversationsApi, type ConversationsApiIface } from \"./conversations.mjs\";\nimport {\n defaultAgentCodec,\n defaultChannelSourceOf,\n defaultLocalCompute,\n defaultLocalHostDial,\n} from \"./defaults.mjs\";\nimport { clientError, ClientErrorCode } from \"./errors.mjs\";\nimport {\n createEventsApi,\n createEventSubscriptionsApi,\n type EventsApiIface,\n type EventSubscriptionsApiIface,\n} from \"./events.mjs\";\nimport { defaultStreamTiming, type StreamTimingIface } from \"./frame-stream.mjs\";\nimport {\n createHttp,\n HttpMethod,\n type AgentClientAuth,\n type FetchIface,\n type HeadersOption,\n} from \"./http.mjs\";\nimport {\n createGatewayRealtimeTransport,\n type GatewayConnect,\n type GatewayRealtimeTransportIface,\n type RealtimeTransportIface,\n} from \"./realtime.mjs\";\nimport type { LocalComputeIface, LocalHostIface, LocalHostSocketIface } from \"./local-host.mjs\";\nimport { createProjectClient, type ProjectClientIface } from \"./project.mjs\";\nimport { createProjectsApi, type ProjectsApiIface } from \"./projects.mjs\";\nimport { createPublishersApi, type PublishersApiIface } from \"./publishers.mjs\";\nimport { createSchedulesApi, type SchedulesApiIface } from \"./schedules.mjs\";\nimport { createSessionsApi, type SessionsApiIface } from \"./sessions.mjs\";\nimport type { AgentStartDepsIface } from \"./start.mjs\";\n\n/** Final's agents API. */\nexport const DEFAULT_AGENTS_HOST = 'https://agent-session.final.ai';\n\nexport interface CreateClientOptionsIface {\n auth: AgentClientAuth;\n /**\n * Whether this process provides the files and shell an agent requires when\n * the caller leaves them out (default true), so the model's file edits and\n * commands run here, on this machine. A server should provide every\n * capability explicitly and pass false, so an omission fails with\n * `requirements_unmet` instead of giving the model a shell in the server.\n */\n localCompute?: boolean;\n /**\n * The agents API origin (default `https://agent-session.final.ai`; its API is\n * under `/api` and ACP at `/acp/ws`), or a base URL the API routes are mounted under.\n */\n host?: string;\n /** Extra headers per request; console clients send their client identity header here. */\n headers?: HeadersOption;\n /** API requests (the host's routes); carries auth and caller headers. */\n fetch?: FetchIface;\n /**\n * Presigned storage requests (attachment uploads). Gets only the headers the\n * presign requires, never auth, client identity or cookies, so a storage\n * bucket's CORS and third-party hosts see nothing of the caller. Defaults to\n * `globalThis.fetch`; keep it free of header-injecting wrappers.\n */\n storageFetch?: FetchIface;\n /** console-web and console-mobile pass their realtime clients; defaults to a gateway connection. */\n realtime?: RealtimeTransportIface;\n /** Seam for the default transport's gateway connection. */\n gatewayConnect?: GatewayConnect;\n /** Seam for stream retry timing (tests). */\n timing?: Partial<StreamTimingIface>;\n /** Seam for idempotency keys and client message ids; defaults to `crypto.randomUUID`. */\n newKey?: () => string;\n /** Seam for the client clock (conversation recovery windows). */\n now?: () => number;\n /** Seam: how agent values become documents and in-process code. */\n agentCodec?: AgentValueCodecIface;\n /** Seam: how a channel value becomes its source. */\n channelSourceOf?: ChannelSourceOf;\n /** Seams for local hosts: the socket, and the sandbox this process serves. */\n localHosts?: {\n /** Opens the local host socket; abandons it when `signal` aborts. */\n dial?: (path: string, signal?: AbortSignal) => Promise<LocalHostSocketIface>;\n compute?: Partial<LocalComputeIface>;\n };\n}\n\nexport interface AgentsApiIface {\n /**\n * The agents the caller can use; with `projectId`, those usable there (its own and those\n * inherited from its ancestors). Without it, everything the caller can access (an API key: its\n * parent project and every project it is granted; a person: every project they can read).\n * Fetch one as data with `client.project({ id }).agents.get`.\n */\n list: (\n options?: SignalOptionsIface & { cursor?: string; limit?: number; projectId?: string },\n ) => Promise<AgentListIface>;\n}\n\nexport interface PeopleApiIface {\n /** One page of the caller's organization members, by name; pass `nextCursor` as `cursor` for the next. */\n list: (\n options?: SignalOptionsIface & { cursor?: string; limit?: number },\n ) => Promise<PersonListIface>;\n /** Every member of the caller's organization (all pages). */\n all: (options?: SignalOptionsIface) => Promise<PersonIface[]>;\n}\n\nexport interface RealtimeApiIface {\n /**\n * Mints a gateway session (`POST /v1/realtime/session`) for the signed-in user:\n * the gateway URL, a short-lived token, and the user id realtime topics are keyed by.\n * Pass it as `createSession` to `createGatewayRealtimeTransport` when supplying a transport.\n */\n createSession: (options?: SignalOptionsIface) => Promise<RealtimeSessionResponseIface>;\n}\n\nexport interface InferenceApiIface {\n /**\n * The vendors and models the platform's own metered inference serves, with\n * prices (`GET /v1/inference/offering`, public). A harness using the\n * platform's inference can run only models listed here.\n */\n offering: (options?: SignalOptionsIface) => Promise<InferenceOfferingIface>;\n}\n\nexport interface PlatformIdentityApiIface {\n /**\n * Exchanges a sandbox-provider (or downstream) assertion the platform issued\n * for a fresh one: for the provider's own URL (a refresh) or a backend its\n * registration was granted. The subject token is the credential.\n */\n exchange: (\n args: PlatformIdentityExchangeRequestIface & SignalOptionsIface,\n ) => Promise<PlatformIdentityExchangeResponseIface>;\n}\n\nexport interface DecisionsApiIface {\n /** One decision awaiting the caller's answer, as `conversations.decisions` lists it. */\n get: (args: { id: string } & SignalOptionsIface) => Promise<DecisionIface>;\n}\n\nexport interface AppApiIface {\n /**\n * The calling app's event subscriptions, across every organization that\n * installed it. Needs an app-level token.\n */\n eventSubscriptions: EventSubscriptionsApiIface;\n}\n\nexport interface AgentClientIface {\n /** One project: where sessions, conversations, sandboxes and integrations are created. */\n project: (args: { id: string }) => ProjectClientIface;\n /** The project tree: list projects and create them. */\n projects: ProjectsApiIface;\n /** The event feed across everything the caller can see; `project({ id }).events` narrows it. */\n events: EventsApiIface;\n app: AppApiIface;\n /** Publishers' public agents, channels, harnesses and ACP adapters. */\n publishers: PublishersApiIface;\n inference: InferenceApiIface;\n platformIdentity: PlatformIdentityApiIface;\n decisions: DecisionsApiIface;\n health: (options?: SignalOptionsIface) => Promise<HealthResponseIface>;\n agents: AgentsApiIface;\n people: PeopleApiIface;\n realtime: RealtimeApiIface;\n /** Existing sessions by id; create them through `project({ id }).sessions`. */\n sessions: SessionsApiIface;\n /** The caller's conversations; create them through `project({ id }).conversations`. */\n conversations: ConversationsApiIface;\n channelBindings: ChannelBindingsApiIface;\n schedules: SchedulesApiIface;\n /**\n * ACP-native access (`/acp/ws`): an ACP v2 ClientApp connection on which the\n * agents API is the agent. The ACP SDK loads on the first `connect`.\n */\n acp: AcpApiIface;\n /**\n * Ends every stream (they reject with a `client_closed` ClientError) and every\n * local host connection (the platform then reports this process's tools and\n * compute as unavailable; sessions carry on) and, when the client created its\n * own realtime transport, closes the gateway connection and cancels its\n * retries. A transport passed in `realtime` belongs to the caller and is left\n * open. Idempotent.\n */\n close: () => void;\n [Symbol.asyncDispose]: () => Promise<void>;\n}\n\nexport const createClient = (options: CreateClientOptionsIface): AgentClientIface => {\n const http = createHttp({\n host: options.host ?? DEFAULT_AGENTS_HOST,\n auth: options.auth,\n headers: options.headers,\n fetch: options.fetch,\n });\n let realtime = options.realtime ?? null;\n let ownTransport: GatewayRealtimeTransportIface | null = null;\n const closing = new AbortController();\n const createRealtimeSession: RealtimeApiIface['createSession'] = (sessionOptions) =>\n http.request({\n method: HttpMethod.Post,\n path: '/v1/realtime/session',\n response: realtimeSessionResponseSchema,\n signal: sessionOptions?.signal,\n });\n let realtimeOwner: Promise<RealtimeSessionResponseIface> | null = null;\n const realtimeOwnerSession = () => {\n if (realtimeOwner != null) return realtimeOwner;\n const pending = createRealtimeSession({ signal: closing.signal });\n realtimeOwner = pending;\n void pending.catch(() => {\n if (realtimeOwner === pending) realtimeOwner = null;\n });\n return pending;\n };\n let realtimeUser: Promise<string> | null = null;\n // Shared by every stream, so it is cancelled only with the client, never by one caller.\n const realtimeUserId: ClientContextIface['realtimeUserId'] = () => {\n if (realtimeUser != null) return realtimeUser;\n const pending = realtimeOwnerSession().then((session) => {\n if (session.userId == null)\n throw new Error('This client authenticates as an API-key owner, not a user');\n return session.userId;\n });\n realtimeUser = pending;\n // A failed (or aborted) read is not cached.\n pending.catch(() => {\n if (realtimeUser === pending) realtimeUser = null;\n });\n return pending;\n };\n const context: ClientContextIface = {\n http,\n closeSignal: closing.signal,\n realtimeUserId,\n // Conversations is the only collection.\n realtimeCollectionTopic: async () => {\n const owner = await realtimeOwnerSession();\n // API keys act in their project, not as members: they reach agents through channels.\n if (owner.userId == null)\n throw new Error('Collection streams belong to users; API-key owners use session streams');\n return agentRealtimeTopics.userConversations(owner.userId);\n },\n storageFetch: options.storageFetch ?? ((input, init) => globalThis.fetch(input, init)),\n realtime: () => {\n if (realtime != null) return realtime;\n ownTransport = createGatewayRealtimeTransport({\n createSession: () => createRealtimeSession(),\n connect: options.gatewayConnect,\n });\n if (closing.signal.aborted) ownTransport.close();\n realtime = ownTransport;\n return realtime;\n },\n timing: { ...defaultStreamTiming, ...options.timing },\n newKey: options.newKey ?? (() => globalThis.crypto.randomUUID()),\n now: options.now ?? Date.now,\n };\n\n const hosts = new Set<LocalHostIface>();\n const localCompute = defaultLocalCompute();\n const start: AgentStartDepsIface = {\n context,\n codec: options.agentCodec ?? defaultAgentCodec,\n localCompute: options.localCompute ?? true,\n compute: { ...localCompute, ...options.localHosts?.compute },\n dial: options.localHosts?.dial ?? defaultLocalHostDial(http),\n hosts,\n };\n const channelSourceOf = options.channelSourceOf ?? defaultChannelSourceOf;\n const clientLevel = { deps: start, projectId: null };\n\n const close = (): void => {\n if (closing.signal.aborted) return;\n closing.abort(\n clientError({ message: 'Agent client closed', status: 0, code: ClientErrorCode.Closed }),\n );\n for (const host of hosts) host.close();\n hosts.clear();\n ownTransport?.close();\n };\n\n return {\n close,\n [Symbol.asyncDispose]: async () => close(),\n health: (healthOptions) =>\n http.request({\n method: HttpMethod.Get,\n path: '/v1/health',\n response: healthResponseSchema,\n signal: healthOptions?.signal,\n }),\n agents: {\n list: (listOptions) =>\n http.request({\n method: HttpMethod.Get,\n path: '/v1/agents',\n query: {\n cursor: listOptions?.cursor,\n limit: listOptions?.limit,\n projectId: listOptions?.projectId,\n },\n response: agentListSchema,\n signal: listOptions?.signal,\n }),\n },\n people: (() => {\n const list: PeopleApiIface['list'] = (listOptions) =>\n http.request({\n method: HttpMethod.Get,\n path: '/v1/people',\n query: { cursor: listOptions?.cursor, limit: listOptions?.limit },\n response: personListSchema,\n signal: listOptions?.signal,\n });\n return {\n list,\n all: async (allOptions) => {\n const all: PersonIface[] = [];\n let cursor: string | undefined;\n for (;;) {\n const next = await list({ cursor, signal: allOptions?.signal });\n all.push(...next.people);\n if (next.nextCursor == null) return all;\n cursor = next.nextCursor;\n }\n },\n };\n })(),\n realtime: { createSession: createRealtimeSession },\n project: ({ id }) => createProjectClient({ context, start, channelSourceOf, projectId: id }),\n projects: createProjectsApi(context),\n events: createEventsApi({ context, projectId: null }),\n app: {\n eventSubscriptions: createEventSubscriptionsApi({\n context,\n basePath: '/v1/apps/me/event-subscriptions',\n }),\n },\n publishers: createPublishersApi(context),\n inference: {\n offering: (offeringOptions) =>\n http.request({\n method: HttpMethod.Get,\n path: '/v1/inference/offering',\n response: inferenceOfferingSchema,\n signal: offeringOptions?.signal,\n }),\n },\n platformIdentity: {\n exchange: ({ signal, ...value }) =>\n http.request({\n method: HttpMethod.Post,\n path: '/v1/platform-identity/exchange',\n body: { schema: platformIdentityExchangeRequestSchema, value },\n response: platformIdentityExchangeResponseSchema,\n signal,\n }),\n },\n decisions: {\n get: async ({ id, signal }) =>\n (\n await http.request({\n method: HttpMethod.Get,\n path: `/v1/decisions/${encodePath(id)}`,\n response: decisionResponseSchema,\n signal,\n context: { decisionId: id },\n })\n ).decision,\n },\n sessions: createSessionsApi(context),\n conversations: createConversationsApi(context, clientLevel),\n channelBindings: createChannelBindingsApi(context),\n schedules: createSchedulesApi(context),\n acp: createAcpApi({ http }),\n };\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -10,7 +10,6 @@ const groupSchema = z.looseObject({ options: z.array(choiceSchema) });
10
10
  const selectSchema = z.looseObject({
11
11
  type: z.string().optional(),
12
12
  configId: z.string().optional(),
13
- id: z.string().optional(),
14
13
  name: z.string().optional(),
15
14
  category: z.string().nullish(),
16
15
  currentValue: z.string(),
@@ -20,7 +19,7 @@ const configSelectsOf = (configOptions) => configOptions.flatMap((option) => {
20
19
  const parsed = selectSchema.safeParse(option);
21
20
  if (!parsed.success) return [];
22
21
  const select = parsed.data;
23
- const configId = select.configId ?? select.id;
22
+ const configId = select.configId;
24
23
  if (configId == null || select.type != null && select.type !== "select") return [];
25
24
  const choices = select.options.flatMap((entry) => {
26
25
  const single = choiceSchema.safeParse(entry);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/agent-client/config-options.ts"],
4
- "sourcesContent": ["import type { AgentSessionIface } from '@finalai/agent-protocol/agent-platform';\nimport * as z from 'zod';\n\n// ACP session config options as a session's harness advertises them\n// (`AgentSessionIface.configOptions`), read as pickers: what the model picker\n// and the reasoning picker render, and what `setConfigOption` takes.\n\nexport type SessionConfigOptionIface = AgentSessionIface['configOptions'][number];\n\n/** ACP's semantic categories (UX only); harnesses may add their own. */\nexport enum ConfigOptionCategory {\n Mode = 'mode',\n Model = 'model',\n ThoughtLevel = 'thought_level',\n}\n\nexport interface ConfigSelectChoiceIface {\n value: string;\n name: string;\n}\n\n/** A single-value selector: `setConfigOption({ configId, value })` with one of `choices`. */\nexport interface ConfigSelectIface {\n configId: string;\n name: string;\n category: string | null;\n currentValue: string;\n choices: ConfigSelectChoiceIface[];\n}\n\nconst choiceSchema = z.looseObject({ value: z.string(), name: z.string().optional() });\nconst groupSchema = z.looseObject({ options: z.array(choiceSchema) });\nconst selectSchema = z.looseObject({\n type: z.string().optional(),\n configId: z.string().optional(),\n id: z.string().optional(),\n name: z.string().optional(),\n category: z.string().nullish(),\n currentValue: z.string(),\n options: z.array(z.union([choiceSchema, groupSchema])),\n});\n\n/** The select options among a session's config options (booleans and unknown types skipped). */\nexport const configSelectsOf = (\n configOptions: readonly SessionConfigOptionIface[],\n): ConfigSelectIface[] =>\n configOptions.flatMap((option) => {\n const parsed = selectSchema.safeParse(option);\n if (!parsed.success) return [];\n const select = parsed.data;\n const configId = select.configId ?? select.id;\n if (configId == null || (select.type != null && select.type !== 'select')) return [];\n const choices = select.options.flatMap((entry) => {\n const single = choiceSchema.safeParse(entry);\n if (single.success) return [single.data];\n return groupSchema.safeParse(entry).data?.options ?? [];\n });\n return [\n {\n configId,\n name: select.name ?? configId,\n category: select.category ?? null,\n currentValue: select.currentValue,\n choices: choices.map((choice) => ({\n value: choice.value,\n name: choice.name ?? choice.value,\n })),\n },\n ];\n });\n\n/** The first select of a category (`model`, `thought_level`), if the harness advertises one. */\nexport const configSelectFor = (\n configOptions: readonly SessionConfigOptionIface[],\n category: ConfigOptionCategory | string,\n): ConfigSelectIface | null =>\n configSelectsOf(configOptions).find((select) => select.category === category) ?? null;\n"],
5
- "mappings": "AACA,YAAY,OAAO;AASZ,IAAK,uBAAL,kBAAKA,0BAAL;AACL,EAAAA,sBAAA,UAAO;AACP,EAAAA,sBAAA,WAAQ;AACR,EAAAA,sBAAA,kBAAe;AAHL,SAAAA;AAAA,GAAA;AAoBZ,MAAM,eAAe,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACrF,MAAM,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,EAAE,CAAC;AACpE,MAAM,eAAe,EAAE,YAAY;AAAA,EACjC,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,IAAI,EAAE,OAAO,EAAE,SAAS;AAAA,EACxB,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,UAAU,EAAE,OAAO,EAAE,QAAQ;AAAA,EAC7B,cAAc,EAAE,OAAO;AAAA,EACvB,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,cAAc,WAAW,CAAC,CAAC;AACvD,CAAC;AAGM,MAAM,kBAAkB,CAC7B,kBAEA,cAAc,QAAQ,CAAC,WAAW;AAChC,QAAM,SAAS,aAAa,UAAU,MAAM;AAC5C,MAAI,CAAC,OAAO,QAAS,QAAO,CAAC;AAC7B,QAAM,SAAS,OAAO;AACtB,QAAM,WAAW,OAAO,YAAY,OAAO;AAC3C,MAAI,YAAY,QAAS,OAAO,QAAQ,QAAQ,OAAO,SAAS,SAAW,QAAO,CAAC;AACnF,QAAM,UAAU,OAAO,QAAQ,QAAQ,CAAC,UAAU;AAChD,UAAM,SAAS,aAAa,UAAU,KAAK;AAC3C,QAAI,OAAO,QAAS,QAAO,CAAC,OAAO,IAAI;AACvC,WAAO,YAAY,UAAU,KAAK,EAAE,MAAM,WAAW,CAAC;AAAA,EACxD,CAAC;AACD,SAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA,MAAM,OAAO,QAAQ;AAAA,MACrB,UAAU,OAAO,YAAY;AAAA,MAC7B,cAAc,OAAO;AAAA,MACrB,SAAS,QAAQ,IAAI,CAAC,YAAY;AAAA,QAChC,OAAO,OAAO;AAAA,QACd,MAAM,OAAO,QAAQ,OAAO;AAAA,MAC9B,EAAE;AAAA,IACJ;AAAA,EACF;AACF,CAAC;AAGI,MAAM,kBAAkB,CAC7B,eACA,aAEA,gBAAgB,aAAa,EAAE,KAAK,CAAC,WAAW,OAAO,aAAa,QAAQ,KAAK;",
4
+ "sourcesContent": ["import type { AgentSessionIface } from '@finalai/agent-protocol/agent-platform';\nimport * as z from 'zod';\n\n// ACP session config options as a session's harness advertises them\n// (`AgentSessionIface.configOptions`), read as pickers: what the model picker\n// and the reasoning picker render, and what `setConfigOption` takes.\n\nexport type SessionConfigOptionIface = AgentSessionIface['configOptions'][number];\n\n/** ACP's semantic categories (UX only); harnesses may add their own. */\nexport enum ConfigOptionCategory {\n Mode = 'mode',\n Model = 'model',\n ThoughtLevel = 'thought_level',\n}\n\nexport interface ConfigSelectChoiceIface {\n value: string;\n name: string;\n}\n\n/** A single-value selector: `setConfigOption({ configId, value })` with one of `choices`. */\nexport interface ConfigSelectIface {\n configId: string;\n name: string;\n category: string | null;\n currentValue: string;\n choices: ConfigSelectChoiceIface[];\n}\n\nconst choiceSchema = z.looseObject({ value: z.string(), name: z.string().optional() });\nconst groupSchema = z.looseObject({ options: z.array(choiceSchema) });\nconst selectSchema = z.looseObject({\n type: z.string().optional(),\n configId: z.string().optional(),\n name: z.string().optional(),\n category: z.string().nullish(),\n currentValue: z.string(),\n options: z.array(z.union([choiceSchema, groupSchema])),\n});\n\n/** The select options among a session's config options (booleans and unknown types skipped). */\nexport const configSelectsOf = (\n configOptions: readonly SessionConfigOptionIface[],\n): ConfigSelectIface[] =>\n configOptions.flatMap((option) => {\n const parsed = selectSchema.safeParse(option);\n if (!parsed.success) return [];\n const select = parsed.data;\n const configId = select.configId;\n if (configId == null || (select.type != null && select.type !== 'select')) return [];\n const choices = select.options.flatMap((entry) => {\n const single = choiceSchema.safeParse(entry);\n if (single.success) return [single.data];\n return groupSchema.safeParse(entry).data?.options ?? [];\n });\n return [\n {\n configId,\n name: select.name ?? configId,\n category: select.category ?? null,\n currentValue: select.currentValue,\n choices: choices.map((choice) => ({\n value: choice.value,\n name: choice.name ?? choice.value,\n })),\n },\n ];\n });\n\n/** The first select of a category (`model`, `thought_level`), if the harness advertises one. */\nexport const configSelectFor = (\n configOptions: readonly SessionConfigOptionIface[],\n category: ConfigOptionCategory | string,\n): ConfigSelectIface | null =>\n configSelectsOf(configOptions).find((select) => select.category === category) ?? null;\n"],
5
+ "mappings": "AACA,YAAY,OAAO;AASZ,IAAK,uBAAL,kBAAKA,0BAAL;AACL,EAAAA,sBAAA,UAAO;AACP,EAAAA,sBAAA,WAAQ;AACR,EAAAA,sBAAA,kBAAe;AAHL,SAAAA;AAAA,GAAA;AAoBZ,MAAM,eAAe,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACrF,MAAM,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,EAAE,CAAC;AACpE,MAAM,eAAe,EAAE,YAAY;AAAA,EACjC,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,UAAU,EAAE,OAAO,EAAE,QAAQ;AAAA,EAC7B,cAAc,EAAE,OAAO;AAAA,EACvB,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,cAAc,WAAW,CAAC,CAAC;AACvD,CAAC;AAGM,MAAM,kBAAkB,CAC7B,kBAEA,cAAc,QAAQ,CAAC,WAAW;AAChC,QAAM,SAAS,aAAa,UAAU,MAAM;AAC5C,MAAI,CAAC,OAAO,QAAS,QAAO,CAAC;AAC7B,QAAM,SAAS,OAAO;AACtB,QAAM,WAAW,OAAO;AACxB,MAAI,YAAY,QAAS,OAAO,QAAQ,QAAQ,OAAO,SAAS,SAAW,QAAO,CAAC;AACnF,QAAM,UAAU,OAAO,QAAQ,QAAQ,CAAC,UAAU;AAChD,UAAM,SAAS,aAAa,UAAU,KAAK;AAC3C,QAAI,OAAO,QAAS,QAAO,CAAC,OAAO,IAAI;AACvC,WAAO,YAAY,UAAU,KAAK,EAAE,MAAM,WAAW,CAAC;AAAA,EACxD,CAAC;AACD,SAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA,MAAM,OAAO,QAAQ;AAAA,MACrB,UAAU,OAAO,YAAY;AAAA,MAC7B,cAAc,OAAO;AAAA,MACrB,SAAS,QAAQ,IAAI,CAAC,YAAY;AAAA,QAChC,OAAO,OAAO;AAAA,QACd,MAAM,OAAO,QAAQ,OAAO;AAAA,MAC9B,EAAE;AAAA,IACJ;AAAA,EACF;AACF,CAAC;AAGI,MAAM,kBAAkB,CAC7B,eACA,aAEA,gBAAgB,aAAa,EAAE,KAAK,CAAC,WAAW,OAAO,aAAa,QAAQ,KAAK;",
6
6
  "names": ["ConfigOptionCategory"]
7
7
  }
@@ -0,0 +1,85 @@
1
+ import { type ApiDecisionIface, type ConversationContextEntryIface, type ConversationContextRole, type ConversationReadGrantIface, type CreateConversationReadGrantRequestIface, type CreateResourceSubscriptionRequestIface, type InputReceiptIface, type PostConversationInputRequestIface, type RaiseConversationDecisionRequestIface, type ResourceSubscriptionIface } from '@finalai/agent-protocol/agent-platform';
2
+ import { type ClientContextIface, type EnumInput, type SignalOptionsIface } from "./context.mjs";
3
+ export interface ConversationLabelsApiIface {
4
+ /**
5
+ * Sets labels in the caller's namespace (`PATCH …/labels`); `null` removes a
6
+ * key and keys not named are kept. Needs `labels:write`. Returns every label
7
+ * the conversation now carries for the caller; `info()` carries them too.
8
+ */
9
+ set: (labels: Record<string, string | null>, options?: SignalOptionsIface) => Promise<Record<string, string>>;
10
+ }
11
+ export interface ConversationContextEntryInputIface {
12
+ role: EnumInput<ConversationContextRole>;
13
+ /** Delivered verbatim; the platform adds no headers. */
14
+ text: string;
15
+ /** The one agent participant it is for; omitted or null for every agent in the conversation. */
16
+ participantId?: string | null;
17
+ }
18
+ export interface ConversationContextApiIface {
19
+ /**
20
+ * Creates or replaces the caller's entry `key` (`PUT …/context/:key`). The
21
+ * agent gets the text at its next turn boundary, and again whenever it
22
+ * changes or the agent's context was compacted or restored.
23
+ */
24
+ set: (key: string, entry: ConversationContextEntryInputIface, options?: SignalOptionsIface) => Promise<ConversationContextEntryIface>;
25
+ /** Stops delivering an entry; the agent is told nothing (write replacement text to tell it). */
26
+ delete: (key: string, options?: SignalOptionsIface & {
27
+ participantId?: string;
28
+ }) => Promise<void>;
29
+ /** The caller's entries. */
30
+ list: (options?: SignalOptionsIface) => Promise<ConversationContextEntryIface[]>;
31
+ }
32
+ export interface ConversationReadGrantsApiIface {
33
+ /** Lets this conversation's agents read one message of another conversation (`POST …/read-grants`). */
34
+ create: (args: CreateConversationReadGrantRequestIface & SignalOptionsIface) => Promise<ConversationReadGrantIface>;
35
+ list: (options?: SignalOptionsIface) => Promise<ConversationReadGrantIface[]>;
36
+ revoke: (args: {
37
+ grantId: string;
38
+ } & SignalOptionsIface) => Promise<ConversationReadGrantIface>;
39
+ }
40
+ export type SendInputArgsIface = Omit<PostConversationInputRequestIface, 'idempotencyKey'> & {
41
+ /** Redelivering the same key from the same caller and `from.id` returns the first receipt; defaults to a new key. */
42
+ idempotencyKey?: string;
43
+ } & SignalOptionsIface;
44
+ export interface ConversationInputsApiIface {
45
+ /**
46
+ * Hands the conversation's agent something to act on that is not a message
47
+ * from a member (`POST …/inputs`). The reply arrives later as the agent's
48
+ * message, captioned with `label` (or "From <from.name>").
49
+ */
50
+ send: (args: SendInputArgsIface) => Promise<InputReceiptIface>;
51
+ }
52
+ export interface ConversationDecisionsApiIface {
53
+ /**
54
+ * Asks the audience a question card (`POST …/decisions`). The caller owns
55
+ * the decision; raising the same `requestKey` again returns it. Its
56
+ * resolution arrives as a `decision.resolved` event carrying `requestKey`.
57
+ */
58
+ raise: (args: RaiseConversationDecisionRequestIface & SignalOptionsIface) => Promise<ApiDecisionIface>;
59
+ /** A decision the caller raised (404 for anyone else's). */
60
+ get: (args: {
61
+ decisionId: string;
62
+ } & SignalOptionsIface) => Promise<ApiDecisionIface>;
63
+ cancel: (args: {
64
+ decisionId: string;
65
+ } & SignalOptionsIface) => Promise<ApiDecisionIface>;
66
+ }
67
+ export interface ResourceSubscriptionsApiIface {
68
+ /** The outside resources the caller's person follows from this conversation. */
69
+ list: (options?: SignalOptionsIface) => Promise<ResourceSubscriptionIface[]>;
70
+ /** Follows a resource; fails with `no_linked_channel` unless a linked channel handles it. */
71
+ create: (args: CreateResourceSubscriptionRequestIface & SignalOptionsIface) => Promise<ResourceSubscriptionIface>;
72
+ /** Stops following; resolves whether a follow ended. */
73
+ delete: (args: {
74
+ resourceKey: string;
75
+ } & SignalOptionsIface) => Promise<boolean>;
76
+ }
77
+ export interface ConversationResourcesIface {
78
+ labels: ConversationLabelsApiIface;
79
+ context: ConversationContextApiIface;
80
+ readGrants: ConversationReadGrantsApiIface;
81
+ inputs: ConversationInputsApiIface;
82
+ decisions: ConversationDecisionsApiIface;
83
+ resourceSubscriptions: ResourceSubscriptionsApiIface;
84
+ }
85
+ export declare const createConversationResources: (context: ClientContextIface, conversationId: string) => ConversationResourcesIface;