@finalai/agents 0.11.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
package/README.md CHANGED
@@ -1,43 +1,228 @@
1
1
  # @finalai/agents
2
2
 
3
- SDK for defining, publishing, and using agents. Authoring helpers are implemented in
4
- `@finalai/agent-definition`; Final-specific bindings come from
5
- `@finalai/final-agent-provider`.
3
+ SDK for defining agents and starting them. An agent is a value that lists every
4
+ part explicitly and states what it requires; whoever starts it provides the
5
+ rest. Nothing is built or deployed: the agent's document travels with the call
6
+ that starts it.
6
7
 
7
8
  ```ts
8
- import { defineAgent } from '@finalai/agents';
9
- import { serverlessPi } from '@finalai/agents/harnesses';
9
+ // agent.ts
10
+ import { defineAgent, defineInProcessTool, defineServerlessTool, markdown } from '@finalai/agents';
11
+ import { FinalHarness } from '@finalai/agents/harnesses';
12
+ import * as z from 'zod';
13
+ import { orders } from './db.js';
10
14
 
11
- export default defineAgent({
12
- name: 'Assistant',
13
- harness: serverlessPi({
14
- credentials: { payer: 'agent-owner', tryInOrder: [{ kind: 'platform' }] },
15
- }),
15
+ // Self-contained, so it runs on Final's runtime even when this app is not running.
16
+ const lookupReleaseNotes = defineServerlessTool({
17
+ description: 'Fetch the published notes for a release.',
18
+ inputSchema: z.object({ version: z.string() }),
19
+ execute: async ({ version }) => {
20
+ const response = await fetch(`https://releases.example.com/${version}.md`);
21
+ return { found: response.ok, notes: response.ok ? await response.text() : null };
22
+ },
23
+ });
24
+
25
+ // Uses this app's database, so it runs in the process that created the session.
26
+ const findOrder = defineInProcessTool({
27
+ description: 'Look up an order by id.',
28
+ inputSchema: z.object({ id: z.string() }),
29
+ execute: async ({ id }) => orders.find(id),
30
+ });
31
+
32
+ export const agent = defineAgent({
33
+ name: 'Release Scout',
34
+ instructions: markdown('./instructions.md', { from: import.meta.url }),
35
+ tools: { lookup_release_notes: lookupReleaseNotes, find_order: findOrder },
36
+ require: {
37
+ harness: {
38
+ permissionMode: 'ask', // a limit: binding
39
+ recommended: { harness: FinalHarness.Pi, model: 'gpt-6.1-sol' }, // a hint
40
+ },
41
+ compute: { files: 'write', shell: 'execute' }, // keyed by capability
42
+ integrations: {
43
+ issues: { description: 'Issue tracker', tools: { deny: ['delete_*'] } },
44
+ },
45
+ },
16
46
  });
17
47
  ```
18
48
 
19
- Use `@finalai/agents/client` for definitions, sessions, conversations, approvals,
20
- attachments, schedules, sandbox access, and realtime. Use `final-agents --help`
21
- for CLI commands. Compilation requires Node 26 and ships its assets through
22
- `agent-definition`.
49
+ ```ts
50
+ // run.ts
51
+ import { createClient } from '@finalai/agents/client';
52
+ import { finalCredits, serverlessPi } from '@finalai/agents/harnesses';
53
+ import { oauth } from '@finalai/agents/integrations';
54
+ import { agent } from './agent.js';
55
+
56
+ const client = createClient({ auth: { apiKey: process.env.FINAL_API_KEY } });
57
+ const project = client.project({ id: 'prj_01JENGINEERING' });
58
+
59
+ const linear = await project.integrations.create({
60
+ name: 'linear',
61
+ mcp: { url: 'https://mcp.linear.app/mcp' },
62
+ auth: oauth({ credential: 'shared' }),
63
+ });
64
+
65
+ // Pi runs as a worker program, in a Workers sandbox the session owns (created for you).
66
+ const { response } = await project.sessions.create({
67
+ agent,
68
+ provide: {
69
+ harness: serverlessPi({
70
+ model: 'gpt-6.1-sol',
71
+ inference: finalCredits(),
72
+ }),
73
+ integrations: { issues: linear },
74
+ },
75
+ message: 'Did 2.4.1 ship?',
76
+ });
77
+ console.log(await response?.text());
78
+ ```
23
79
 
24
- Credential-chain declarations select which credentials an agent may use and in
25
- which order. Set the payer policy explicitly in the harness configuration.
80
+ ## Requirements and `provide`
26
81
 
27
- For custom provider implementations, import contracts from `@finalai/agent-provider`,
28
- sandbox adapters from `@finalai/agent-provider/sandbox`, and conformance tools from
29
- `@finalai/agent-provider/conformance`. Run a harness check with
30
- `final-agents conformance ./harness.ts`.
82
+ | The agent declares | The caller provides | If not provided |
83
+ | ------------------------------------------------------- | ------------------------ | --------------------------------------------------------------------------------------------------- |
84
+ | `require.harness`: a permission ceiling, a hint | harness settings, inline | the call fails; a harness is never optional |
85
+ | `require.compute.<capability>`: the access it needs | a sandbox per capability | `files` and `shell` run in the calling process; `computerUse` and `browserUse` fail unless optional |
86
+ | `require.integrations.<slot>`: a description, a ceiling | an integration per slot | the call fails, unless the slot is `optional: true` and its tools are simply absent |
31
87
 
32
- Use `FINAL_API_HOST` with `FINAL_API_KEY` to select a deployment once for build and
33
- publish; an explicit `--host` overrides it. Use `defineHostedConnection` for a named
34
- connection resolved by hosting at session start. `defineFinalConnection()` uses
35
- the same path with the `final` binding. Explicit URL declarations remain static.
36
- See the repository's [hosting guide](HOSTING.md) for provider contexts,
37
- resource lookup, and the required hosting integration.
88
+ `provide` is a plain object on every call that starts work:
89
+ `project.sessions.create`, `project.conversations.create` (per participant),
90
+ `conversations.direct` and `.home`, `handle.addParticipant`,
91
+ `handle.participants.provide(participantId, patch)` and
92
+ `project.channels.install({ agents: { provide } })`. Sandbox and integration
93
+ handles are sent as their ids. Before sending, the SDK runs the same
94
+ requirements check the platform runs; anything missing throws a
95
+ `requirements_unmet` error with the list (`isRequirementsUnmetError(cause)`,
96
+ `cause.requirements`), and nothing is created.
38
97
 
39
- Local previews can use explicitly declared secrets from `AGENT_LOCAL_SECRETS_JSON`. Installed app operations and member and chat capabilities require an authenticated host. Embedders may supply the same opaque credential facade to `startDevServer`; raw application credentials are never exposed to authored modules.
98
+ `sessions.create` and `conversations.create` take an `id` you choose, so a
99
+ sandbox created first can be owned by the session or conversation it is for
100
+ (`project.sandboxes.create(environment, { setup, ownedBy, idempotencyKey })`).
101
+ `conversations.findHome()` and `findDirect({ agent })` look up without creating.
102
+
103
+ ## Where things run
104
+
105
+ - **The model's files and shell** run on whatever sandbox is provided
106
+ (`computer(...)` and `device(...)` from `@finalai/agents/sandboxes`, or any
107
+ provider). Left out, they run in the process that created the session, on its
108
+ machine, over a connection the client opens to the platform.
109
+ - **An in-process tool or hook** runs in the process that created the session
110
+ and can use anything that process holds. When that process exits the session
111
+ carries on and the tool reports itself unavailable.
112
+ - **A serverless tool or hook** is self-contained: its source is part of the
113
+ agent's data and it runs on Final's runtime. It cannot import packages or use
114
+ outside variables; bundle a library into one module and pass it as `source`.
115
+
116
+ The compute default is not safe for a server: a backend that leaves out `shell`
117
+ gives the model a shell in that backend. A server provides every capability and
118
+ creates its client with `createClient({ auth, localCompute: false })`, so an
119
+ omission fails instead.
120
+
121
+ An agent is always passed as an object: the value you defined, or one fetched
122
+ with `project.agents.get({ name } | { id } | { hash })`. A fetched agent is data
123
+ only; starting one that has in-process tools fails and names them.
124
+
125
+ ## Harnesses, inference and integrations
126
+
127
+ `@finalai/agents/harnesses` builds harness settings for Final's harnesses
128
+ (`serverlessPi`, `serverlessFinal`, `serverlessNanocodeClaude`,
129
+ `serverlessNanocodeCodex` as worker programs; `claudeCode` and `codex` as a
130
+ process on a machine, or `environment: atUrl({ url, hop })` for one already
131
+ running) and the inference sources a harness pays with, first available wins:
132
+
133
+ ```ts
134
+ serverlessNanocodeClaude({
135
+ model: 'claude-opus-5-5',
136
+ inference: [subscription(), apiKey('ANTHROPIC_API_KEY'), finalCredits()],
137
+ });
138
+ ```
139
+
140
+ `project.harnesses.check({ agent, harness })` says whether settings suit an
141
+ agent and where the harness would run.
142
+
143
+ A harness is data you can define and publish yourself, with the ACP adapter it
144
+ runs behind when it does not speak ACP v2:
145
+
146
+ ```ts
147
+ import {
148
+ CredentialDelivery,
149
+ defineHarness,
150
+ InferenceSourceKind,
151
+ PermissionLevel,
152
+ } from '@finalai/agents';
153
+
154
+ export const harness = defineHarness({
155
+ configurationSchema: { type: 'object', properties: { model: { type: 'string' } } },
156
+ features: [],
157
+ lowestPermission: PermissionLevel.Ask,
158
+ inference: { kinds: [InferenceSourceKind.ApiKey], delivery: CredentialDelivery.AtOpen },
159
+ native: { files: {}, shell: {} },
160
+ interface: 'my-cli-rpc',
161
+ adapter: 'my-cli-acp',
162
+ run: {
163
+ process: {
164
+ command: 'my-cli',
165
+ args: [
166
+ '--rpc',
167
+ { when: 'configuration.model', args: ['--model', '{{configuration.model}}'] },
168
+ ],
169
+ },
170
+ },
171
+ });
172
+ ```
173
+
174
+ `project.harnesses.publish({ harness, name })` and
175
+ `project.acpAdapters.publish({ adapter, name })` give them names harness
176
+ settings use (`{ harness: 'my-cli', environment: box }`).
177
+ `project.harnesses.allowances` lists, allows and revokes the harnesses
178
+ subscriptions may reach. A harness reached some other way (a hosted fleet)
179
+ carries its own code: `defineHarness({ …, provider: defineHarnessProvider({ open,
180
+ resume, park, close, health }) })`, self-contained like a serverless tool. `@finalai/agents/integrations` has the auth builders (`oauth`, `secret`,
181
+ `platformIdentity`) and `finalGateway({ url })`. A person's own sign-in is never a
182
+ requirement: the platform asks them on first use.
183
+
184
+ ## Publishing
185
+
186
+ ```sh
187
+ final-agents print ./agent.ts # the document as JSON; calls nothing
188
+ final-agents publish ./agent.ts --name release-scout # FINAL_API_KEY, FINAL_PROJECT_ID
189
+ final-agents publish ./harness.ts --name my-cli # a harness or ACP adapter export
190
+ ```
191
+
192
+ `publish` is `project.agents.publish({ agent, name })`: it stores the document
193
+ by its content hash and points the name at it. `project.agents.parse(json)`
194
+ reads a printed document back as an agent. `final-agents conformance ./harness.ts`
195
+ runs the harness conformance kit.
196
+
197
+ A project that claims a publisher handle (`project.publisher.claim({ handle })`)
198
+ can make names public: `publish({ …, visibility: 'public' })`, or
199
+ `project.publicNames.publish({ kind, name })`. Any organization then names them
200
+ as `handle/name`, and `client.publishers.get(handle)` lists them.
201
+
202
+ ## Events and webhooks
203
+
204
+ `project.events.list({ after })` reads what changed in a project and those
205
+ below it, in commit order; `project.events.stream()` keeps polling.
206
+ `project.eventSubscriptions.create({ url, kinds })` pushes the same events to
207
+ your endpoint, signed per Standard Webhooks:
208
+
209
+ ```ts
210
+ import { verifyWebhook } from '@finalai/agents/webhooks';
211
+
212
+ const result = await verifyWebhook({
213
+ payload: await request.text(),
214
+ headers: request.headers,
215
+ secret,
216
+ });
217
+ if (!result.ok) return new Response(null, { status: 400 });
218
+ for (const event of result.delivery.events) {
219
+ // Payloads are ids and state; read details through the API.
220
+ }
221
+ ```
40
222
 
41
- Authored channel applications use `defineChannel` from `/channels` and compile into the published bundle. Use `bundleRef('channels/support')` in `agent.ts` to configure an existing channel module; its credentials and routes are derived from that module. Credential enums and opaque credential types are available from the same facade.
223
+ `@finalai/agents/verify` verifies the tokens the platform signs: the
224
+ platform-identity assertions your integrations and providers receive, and access tokens.
42
225
 
43
- `client.definitions.publish({ definition, ref, activate: false })` publishes an approved immutable source revision without changing the live agent, routes, listeners, or schedules. The CLI equivalent is `publish --no-activate`. Credential declarations still need normal administrator approval. Install an exported channel with `channel install <key> --revision <id> --project <id> --install <id>`; use `--replace` or `channelBindings.create({ ..., replace: true })` to explicitly update an active binding while retaining its ID and binding base URL. Omitted configuration preserves current settings during replacement; an explicit empty configuration resets to source defaults. New source publication never silently updates an installed revision pin.
226
+ See [examples/release-scout](examples/release-scout) and the repository's
227
+ [hosting guide](HOSTING.md) for what a platform implementing the API
228
+ provides, including the local host connection.
@@ -0,0 +1,24 @@
1
+ import { type AgentDocumentIface } from '@finalai/agent-provider/document';
2
+ import type { InProcessCodeRegistryIface } from '@finalai/agent-provider/code-host';
3
+ import { type AgentInfoIface, type AgentRefInputIface } from '@finalai/agent-protocol/agent-platform';
4
+ /** What `defineAgent` returns; read through `AgentValueCodecIface`. */
5
+ export type AgentValue = object;
6
+ /** An agent as `sessions.create` and participants take it. */
7
+ export type AgentInput = AgentInfoIface | AgentValue;
8
+ /** How the SDK reads an agent value; a seam over `@finalai/agent-definition`. */
9
+ export interface AgentValueCodecIface {
10
+ documentOf: (agent: AgentValue) => AgentDocumentIface | Promise<AgentDocumentIface>;
11
+ /** The bodies of its in-process tools, hooks and approval predicates. */
12
+ inProcessCodeOf: (agent: AgentValue) => InProcessCodeRegistryIface | Promise<InProcessCodeRegistryIface>;
13
+ }
14
+ export interface ResolvedAgentIface {
15
+ hash: string;
16
+ document: AgentDocumentIface;
17
+ /** The ref sent on the wire; the document travels with a value. */
18
+ ref: AgentRefInputIface;
19
+ /** Names of its tools and hooks whose code only runs in the creating process. */
20
+ inProcess: string[];
21
+ /** Null when this process does not hold the agent's code (a fetched agent). */
22
+ code: InProcessCodeRegistryIface | null;
23
+ }
24
+ export declare const resolveAgentInput: (agent: unknown, codec: AgentValueCodecIface) => Promise<ResolvedAgentIface>;
@@ -0,0 +1,46 @@
1
+ import {
2
+ agentDocumentHash,
3
+ agentDocumentSchema,
4
+ inProcessCodeOf
5
+ } from "@finalai/agent-provider/document";
6
+ import { jsonObjectSchema } from "@finalai/agent-protocol";
7
+ import {
8
+ agentInfoSchema
9
+ } from "@finalai/agent-protocol/agent-platform";
10
+ import { clientError, ClientErrorCode } from "./errors.mjs";
11
+ const invalidAgent = (message) => clientError({ message, status: 0, code: ClientErrorCode.InvalidRequest });
12
+ const resolveAgentInput = async (agent, codec) => {
13
+ if (typeof agent === "string")
14
+ throw invalidAgent(
15
+ `An agent is passed as an object, not the string "${agent}": pass the value you defined, or fetch it with project.agents.get({ name })`
16
+ );
17
+ if (agent == null || typeof agent !== "object")
18
+ throw invalidAgent("An agent is passed as the value you defined or one you fetched");
19
+ const fetched = agentInfoSchema.safeParse(agent);
20
+ if (fetched.success) {
21
+ const document2 = agentDocumentSchema.safeParse(fetched.data.document);
22
+ if (!document2.success)
23
+ throw invalidAgent(`The fetched agent's document is not valid: ${document2.error.message}`);
24
+ return {
25
+ hash: fetched.data.hash,
26
+ document: document2.data,
27
+ // A published agent is stored; one parsed from a printed document may not be.
28
+ ref: fetched.data.id == null ? { hash: fetched.data.hash, document: fetched.data.document } : { hash: fetched.data.hash },
29
+ inProcess: inProcessCodeOf(document2.data),
30
+ code: null
31
+ };
32
+ }
33
+ const document = await codec.documentOf(agent);
34
+ const hash = await agentDocumentHash(document);
35
+ return {
36
+ hash,
37
+ document,
38
+ ref: { hash, document: jsonObjectSchema.parse(JSON.parse(JSON.stringify(document))) },
39
+ inProcess: inProcessCodeOf(document),
40
+ code: await codec.inProcessCodeOf(agent)
41
+ };
42
+ };
43
+ export {
44
+ resolveAgentInput
45
+ };
46
+ //# sourceMappingURL=agent-input.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/agent-client/agent-input.ts"],
4
+ "sourcesContent": ["import {\n agentDocumentHash,\n agentDocumentSchema,\n inProcessCodeOf,\n type AgentDocumentIface,\n} from '@finalai/agent-provider/document';\nimport type { InProcessCodeRegistryIface } from '@finalai/agent-provider/code-host';\nimport { jsonObjectSchema } from '@finalai/agent-protocol';\nimport {\n agentInfoSchema,\n type AgentInfoIface,\n type AgentRefInputIface,\n} from '@finalai/agent-protocol/agent-platform';\nimport { clientError, ClientErrorCode } from \"./errors.mjs\";\n\n// An agent is always passed as an object: a value the caller defined\n// (`defineAgent`), whose in-process code this process holds, or one fetched\n// with `project.agents.get`, which is data only.\n\n/** What `defineAgent` returns; read through `AgentValueCodecIface`. */\nexport type AgentValue = object;\n\n/** An agent as `sessions.create` and participants take it. */\nexport type AgentInput = AgentInfoIface | AgentValue;\n\n/** How the SDK reads an agent value; a seam over `@finalai/agent-definition`. */\nexport interface AgentValueCodecIface {\n documentOf: (agent: AgentValue) => AgentDocumentIface | Promise<AgentDocumentIface>;\n /** The bodies of its in-process tools, hooks and approval predicates. */\n inProcessCodeOf: (\n agent: AgentValue,\n ) => InProcessCodeRegistryIface | Promise<InProcessCodeRegistryIface>;\n}\n\nexport interface ResolvedAgentIface {\n hash: string;\n document: AgentDocumentIface;\n /** The ref sent on the wire; the document travels with a value. */\n ref: AgentRefInputIface;\n /** Names of its tools and hooks whose code only runs in the creating process. */\n inProcess: string[];\n /** Null when this process does not hold the agent's code (a fetched agent). */\n code: InProcessCodeRegistryIface | null;\n}\n\nconst invalidAgent = (message: string) =>\n clientError({ message, status: 0, code: ClientErrorCode.InvalidRequest });\n\nexport const resolveAgentInput = async (\n agent: unknown,\n codec: AgentValueCodecIface,\n): Promise<ResolvedAgentIface> => {\n if (typeof agent === 'string')\n throw invalidAgent(\n `An agent is passed as an object, not the string \"${agent}\": pass the value you defined, or fetch it with project.agents.get({ name })`,\n );\n if (agent == null || typeof agent !== 'object')\n throw invalidAgent('An agent is passed as the value you defined or one you fetched');\n const fetched = agentInfoSchema.safeParse(agent);\n if (fetched.success) {\n const document = agentDocumentSchema.safeParse(fetched.data.document);\n if (!document.success)\n throw invalidAgent(`The fetched agent's document is not valid: ${document.error.message}`);\n return {\n hash: fetched.data.hash,\n document: document.data,\n // A published agent is stored; one parsed from a printed document may not be.\n ref:\n fetched.data.id == null\n ? { hash: fetched.data.hash, document: fetched.data.document }\n : { hash: fetched.data.hash },\n inProcess: inProcessCodeOf(document.data),\n code: null,\n };\n }\n const document = await codec.documentOf(agent);\n const hash = await agentDocumentHash(document);\n return {\n hash,\n document,\n ref: { hash, document: jsonObjectSchema.parse(JSON.parse(JSON.stringify(document))) },\n inProcess: inProcessCodeOf(document),\n code: await codec.inProcessCodeOf(agent),\n };\n};\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAEP,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,OAGK;AACP,SAAS,aAAa,uBAAuB;AAgC7C,MAAM,eAAe,CAAC,YACpB,YAAY,EAAE,SAAS,QAAQ,GAAG,MAAM,gBAAgB,eAAe,CAAC;AAEnE,MAAM,oBAAoB,OAC/B,OACA,UACgC;AAChC,MAAI,OAAO,UAAU;AACnB,UAAM;AAAA,MACJ,oDAAoD,KAAK;AAAA,IAC3D;AACF,MAAI,SAAS,QAAQ,OAAO,UAAU;AACpC,UAAM,aAAa,gEAAgE;AACrF,QAAM,UAAU,gBAAgB,UAAU,KAAK;AAC/C,MAAI,QAAQ,SAAS;AACnB,UAAMA,YAAW,oBAAoB,UAAU,QAAQ,KAAK,QAAQ;AACpE,QAAI,CAACA,UAAS;AACZ,YAAM,aAAa,8CAA8CA,UAAS,MAAM,OAAO,EAAE;AAC3F,WAAO;AAAA,MACL,MAAM,QAAQ,KAAK;AAAA,MACnB,UAAUA,UAAS;AAAA;AAAA,MAEnB,KACE,QAAQ,KAAK,MAAM,OACf,EAAE,MAAM,QAAQ,KAAK,MAAM,UAAU,QAAQ,KAAK,SAAS,IAC3D,EAAE,MAAM,QAAQ,KAAK,KAAK;AAAA,MAChC,WAAW,gBAAgBA,UAAS,IAAI;AAAA,MACxC,MAAM;AAAA,IACR;AAAA,EACF;AACA,QAAM,WAAW,MAAM,MAAM,WAAW,KAAK;AAC7C,QAAM,OAAO,MAAM,kBAAkB,QAAQ;AAC7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,KAAK,EAAE,MAAM,UAAU,iBAAiB,MAAM,KAAK,MAAM,KAAK,UAAU,QAAQ,CAAC,CAAC,EAAE;AAAA,IACpF,WAAW,gBAAgB,QAAQ;AAAA,IACnC,MAAM,MAAM,MAAM,gBAAgB,KAAK;AAAA,EACzC;AACF;",
6
+ "names": ["document"]
7
+ }
@@ -1,7 +1,49 @@
1
- import { type ChannelRouteIface, type ChannelSeenPlaceIface, type ConnectChannelPlaceRequestIface, type CreateChannelBindingRequestIface, type CreateChannelBindingResponseIface } from '@finalai/agent-protocol/agent-platform';
2
- import { type ClientContextIface, type SignalOptionsIface } from "./context.mjs";
1
+ import { type ChannelIface, type ChannelRouteIface, type ChannelSeenPlaceIface, type ConnectChannelPlaceRequestIface, type CreateChannelBindingResponseIface, type DefinitionVisibility, type PublishChannelResponseIface } from '@finalai/agent-protocol/agent-platform';
2
+ import { type ClientContextIface, type EnumInput, type SignalOptionsIface } from "./context.mjs";
3
+ import { type ProvideIface } from "./provide.mjs";
4
+ /** A channel value's source, as `channels.publish({ channel })` sends it. */
5
+ export interface ChannelSourceIface {
6
+ source: string;
7
+ export?: string;
8
+ }
9
+ /** How the SDK turns a channel value into its source; a seam over `@finalai/agent-definition`. */
10
+ export type ChannelSourceOf = (channel: object) => ChannelSourceIface;
11
+ export type PublishChannelArgsIface = {
12
+ name: string;
13
+ /** `public` also makes the name public under the project's publisher handle. */
14
+ visibility?: EnumInput<DefinitionVisibility>;
15
+ } & SignalOptionsIface & ({
16
+ channel: object;
17
+ } | {
18
+ source: string;
19
+ export?: string;
20
+ });
21
+ export interface InstallChannelArgsIface extends SignalOptionsIface {
22
+ /** A published channel (`channels.get`), or `{ name }` to install what the name points at now. */
23
+ channel: Pick<ChannelIface, 'hash'> | {
24
+ name: string;
25
+ };
26
+ connectorInstallId: string;
27
+ /** What an agent gets in every chat this install creates. */
28
+ agents: {
29
+ provide: ProvideIface;
30
+ };
31
+ /** Explicitly replace an existing install of the same connector. */
32
+ replace?: boolean;
33
+ /** Reaches only the channel's own code. */
34
+ config?: Record<string, unknown>;
35
+ }
36
+ export interface ProjectChannelsApiIface {
37
+ publish: (args: PublishChannelArgsIface) => Promise<PublishChannelResponseIface>;
38
+ get: (selector: ({
39
+ name: string;
40
+ } | {
41
+ hash: string;
42
+ }) & SignalOptionsIface) => Promise<ChannelIface>;
43
+ /** Fails with `requirements_unmet` unless `agents.provide` meets the answering agent's requirements. */
44
+ install: (args: InstallChannelArgsIface) => Promise<CreateChannelBindingResponseIface>;
45
+ }
3
46
  export interface ChannelBindingsApiIface {
4
- create(args: CreateChannelBindingRequestIface & SignalOptionsIface): Promise<CreateChannelBindingResponseIface>;
5
47
  places(args: {
6
48
  bindingId: string;
7
49
  } & SignalOptionsIface): Promise<ChannelSeenPlaceIface[]>;
@@ -20,4 +62,11 @@ export interface ChannelBindingsApiIface {
20
62
  ok: boolean;
21
63
  }>;
22
64
  }
65
+ export declare const createProjectChannelsApi: (args: {
66
+ context: ClientContextIface;
67
+ projectId: string;
68
+ sourceOf: ChannelSourceOf;
69
+ }) => ProjectChannelsApiIface;
23
70
  export declare const createChannelBindingsApi: (ctx: ClientContextIface) => ChannelBindingsApiIface;
71
+ /** The default `ChannelSourceOf` when no codec is available. */
72
+ export declare const noChannelSource: ChannelSourceOf;
@@ -1,22 +1,74 @@
1
1
  import {
2
2
  channelPlacesResponseSchema,
3
3
  channelRoutesResponseSchema,
4
+ channelSchema,
4
5
  connectChannelPlaceRequestSchema,
5
6
  connectChannelPlaceResponseSchema,
6
7
  createChannelBindingRequestSchema,
7
8
  createChannelBindingResponseSchema,
8
- disconnectChannelRouteResponseSchema
9
+ disconnectChannelRouteResponseSchema,
10
+ publishChannelRequestSchema,
11
+ publishChannelResponseSchema
9
12
  } from "@finalai/agent-protocol/agent-platform";
10
- import { encodePath } from "./context.mjs";
13
+ import {
14
+ encodePath
15
+ } from "./context.mjs";
16
+ import { clientError, ClientErrorCode } from "./errors.mjs";
11
17
  import { HttpMethod } from "./http.mjs";
18
+ import { provideDocumentOf } from "./provide.mjs";
19
+ const channelsPath = (projectId, suffix) => `/v1/projects/${encodePath(projectId)}/channels${suffix}`;
20
+ const createProjectChannelsApi = (args) => {
21
+ const { http } = args.context;
22
+ return {
23
+ publish: (publish) => {
24
+ const source = "channel" in publish ? args.sourceOf(publish.channel) : {
25
+ source: publish.source,
26
+ ...publish.export == null ? {} : { export: publish.export }
27
+ };
28
+ return http.request({
29
+ method: HttpMethod.Post,
30
+ path: channelsPath(args.projectId, "/publish"),
31
+ body: {
32
+ schema: publishChannelRequestSchema,
33
+ value: { name: publish.name, ...source, visibility: publish.visibility }
34
+ },
35
+ response: publishChannelResponseSchema,
36
+ signal: publish.signal
37
+ });
38
+ },
39
+ get: ({ signal, ...selector }) => http.request({
40
+ method: HttpMethod.Get,
41
+ path: channelsPath(args.projectId, "/lookup"),
42
+ query: {
43
+ name: "name" in selector ? selector.name : void 0,
44
+ hash: "hash" in selector ? selector.hash : void 0
45
+ },
46
+ response: channelSchema,
47
+ signal
48
+ }),
49
+ install: (install) => {
50
+ const channel = "hash" in install.channel ? { hash: install.channel.hash } : { name: install.channel.name };
51
+ return http.request({
52
+ method: HttpMethod.Post,
53
+ path: "/v1/channel-bindings",
54
+ body: {
55
+ schema: createChannelBindingRequestSchema,
56
+ value: {
57
+ projectId: args.projectId,
58
+ channel,
59
+ connectorInstallId: install.connectorInstallId,
60
+ agents: { provide: provideDocumentOf(install.agents.provide) },
61
+ replace: install.replace,
62
+ config: install.config
63
+ }
64
+ },
65
+ response: createChannelBindingResponseSchema,
66
+ signal: install.signal
67
+ });
68
+ }
69
+ };
70
+ };
12
71
  const createChannelBindingsApi = (ctx) => ({
13
- create: ({ signal, ...body }) => ctx.http.request({
14
- method: HttpMethod.Post,
15
- path: "/v1/channel-bindings",
16
- body: { schema: createChannelBindingRequestSchema, value: body },
17
- response: createChannelBindingResponseSchema,
18
- signal
19
- }),
20
72
  places: async ({ bindingId, signal }) => (await ctx.http.request({
21
73
  method: HttpMethod.Get,
22
74
  path: `/v1/channel-bindings/${encodePath(bindingId)}/places`,
@@ -43,7 +95,16 @@ const createChannelBindingsApi = (ctx) => ({
43
95
  signal
44
96
  })
45
97
  });
98
+ const noChannelSource = () => {
99
+ throw clientError({
100
+ message: "Publish a channel as `source`: this build cannot capture a channel value",
101
+ status: 0,
102
+ code: ClientErrorCode.InvalidRequest
103
+ });
104
+ };
46
105
  export {
47
- createChannelBindingsApi
106
+ createChannelBindingsApi,
107
+ createProjectChannelsApi,
108
+ noChannelSource
48
109
  };
49
110
  //# sourceMappingURL=channels.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/agent-client/channels.ts"],
4
- "sourcesContent": ["import {\n channelPlacesResponseSchema,\n channelRoutesResponseSchema,\n connectChannelPlaceRequestSchema,\n connectChannelPlaceResponseSchema,\n createChannelBindingRequestSchema,\n createChannelBindingResponseSchema,\n disconnectChannelRouteResponseSchema,\n type ChannelRouteIface,\n type ChannelSeenPlaceIface,\n type ConnectChannelPlaceRequestIface,\n type CreateChannelBindingRequestIface,\n type CreateChannelBindingResponseIface,\n} from '@finalai/agent-protocol/agent-platform';\nimport { encodePath, type ClientContextIface, type SignalOptionsIface } from \"./context.mjs\";\nimport { HttpMethod } from \"./http.mjs\";\nexport interface ChannelBindingsApiIface {\n create(\n args: CreateChannelBindingRequestIface & SignalOptionsIface,\n ): Promise<CreateChannelBindingResponseIface>;\n places(args: { bindingId: string } & SignalOptionsIface): Promise<ChannelSeenPlaceIface[]>;\n routes(args: { conversationId: string } & SignalOptionsIface): Promise<ChannelRouteIface[]>;\n connect(\n args: ConnectChannelPlaceRequestIface & { conversationId: string } & SignalOptionsIface,\n ): Promise<{ id: string }>;\n disconnect(\n args: { conversationId: string; routeId: string } & SignalOptionsIface,\n ): Promise<{ ok: boolean }>;\n}\nexport const createChannelBindingsApi = (ctx: ClientContextIface): ChannelBindingsApiIface => ({\n create: ({ signal, ...body }) =>\n ctx.http.request({\n method: HttpMethod.Post,\n path: '/v1/channel-bindings',\n body: { schema: createChannelBindingRequestSchema, value: body },\n response: createChannelBindingResponseSchema,\n signal,\n }),\n places: async ({ bindingId, signal }) =>\n (\n await ctx.http.request({\n method: HttpMethod.Get,\n path: `/v1/channel-bindings/${encodePath(bindingId)}/places`,\n response: channelPlacesResponseSchema,\n signal,\n })\n ).places,\n routes: async ({ conversationId, signal }) =>\n (\n await ctx.http.request({\n method: HttpMethod.Get,\n path: `/v1/conversations/${encodePath(conversationId)}/channel-routes`,\n response: channelRoutesResponseSchema,\n signal,\n })\n ).routes,\n connect: ({ conversationId, signal, ...body }) =>\n ctx.http.request({\n method: HttpMethod.Post,\n path: `/v1/conversations/${encodePath(conversationId)}/channel-routes`,\n body: { schema: connectChannelPlaceRequestSchema, value: body },\n response: connectChannelPlaceResponseSchema,\n signal,\n }),\n disconnect: ({ conversationId, routeId, signal }) =>\n ctx.http.request({\n method: HttpMethod.Delete,\n path: `/v1/conversations/${encodePath(conversationId)}/channel-routes/${encodePath(routeId)}`,\n response: disconnectChannelRouteResponseSchema,\n signal,\n }),\n});\n"],
5
- "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AACP,SAAS,kBAAoE;AAC7E,SAAS,kBAAkB;AAcpB,MAAM,2BAA2B,CAAC,SAAsD;AAAA,EAC7F,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,MACzB,IAAI,KAAK,QAAQ;AAAA,IACf,QAAQ,WAAW;AAAA,IACnB,MAAM;AAAA,IACN,MAAM,EAAE,QAAQ,mCAAmC,OAAO,KAAK;AAAA,IAC/D,UAAU;AAAA,IACV;AAAA,EACF,CAAC;AAAA,EACH,QAAQ,OAAO,EAAE,WAAW,OAAO,OAE/B,MAAM,IAAI,KAAK,QAAQ;AAAA,IACrB,QAAQ,WAAW;AAAA,IACnB,MAAM,wBAAwB,WAAW,SAAS,CAAC;AAAA,IACnD,UAAU;AAAA,IACV;AAAA,EACF,CAAC,GACD;AAAA,EACJ,QAAQ,OAAO,EAAE,gBAAgB,OAAO,OAEpC,MAAM,IAAI,KAAK,QAAQ;AAAA,IACrB,QAAQ,WAAW;AAAA,IACnB,MAAM,qBAAqB,WAAW,cAAc,CAAC;AAAA,IACrD,UAAU;AAAA,IACV;AAAA,EACF,CAAC,GACD;AAAA,EACJ,SAAS,CAAC,EAAE,gBAAgB,QAAQ,GAAG,KAAK,MAC1C,IAAI,KAAK,QAAQ;AAAA,IACf,QAAQ,WAAW;AAAA,IACnB,MAAM,qBAAqB,WAAW,cAAc,CAAC;AAAA,IACrD,MAAM,EAAE,QAAQ,kCAAkC,OAAO,KAAK;AAAA,IAC9D,UAAU;AAAA,IACV;AAAA,EACF,CAAC;AAAA,EACH,YAAY,CAAC,EAAE,gBAAgB,SAAS,OAAO,MAC7C,IAAI,KAAK,QAAQ;AAAA,IACf,QAAQ,WAAW;AAAA,IACnB,MAAM,qBAAqB,WAAW,cAAc,CAAC,mBAAmB,WAAW,OAAO,CAAC;AAAA,IAC3F,UAAU;AAAA,IACV;AAAA,EACF,CAAC;AACL;",
4
+ "sourcesContent": ["import {\n channelPlacesResponseSchema,\n channelRoutesResponseSchema,\n channelSchema,\n connectChannelPlaceRequestSchema,\n connectChannelPlaceResponseSchema,\n createChannelBindingRequestSchema,\n createChannelBindingResponseSchema,\n disconnectChannelRouteResponseSchema,\n publishChannelRequestSchema,\n publishChannelResponseSchema,\n type ChannelIface,\n type ChannelRouteIface,\n type ChannelSeenPlaceIface,\n type ConnectChannelPlaceRequestIface,\n type CreateChannelBindingResponseIface,\n type DefinitionVisibility,\n type PublishChannelResponseIface,\n} from '@finalai/agent-protocol/agent-platform';\nimport {\n encodePath,\n type ClientContextIface,\n type EnumInput,\n type SignalOptionsIface,\n} from \"./context.mjs\";\nimport { clientError, ClientErrorCode } from \"./errors.mjs\";\nimport { HttpMethod } from \"./http.mjs\";\nimport { provideDocumentOf, type ProvideIface } from \"./provide.mjs\";\n\n// Channels connect a provider (Slack, email, a webhook) to a project's chats.\n// A channel is one self-contained module, published by name and stored by\n// content hash; its handlers always run on Final's serverless runtime.\n\n/** A channel value's source, as `channels.publish({ channel })` sends it. */\nexport interface ChannelSourceIface {\n source: string;\n export?: string;\n}\n\n/** How the SDK turns a channel value into its source; a seam over `@finalai/agent-definition`. */\nexport type ChannelSourceOf = (channel: object) => ChannelSourceIface;\n\nexport type PublishChannelArgsIface = {\n name: string;\n /** `public` also makes the name public under the project's publisher handle. */\n visibility?: EnumInput<DefinitionVisibility>;\n} & SignalOptionsIface &\n ({ channel: object } | { source: string; export?: string });\n\nexport interface InstallChannelArgsIface extends SignalOptionsIface {\n /** A published channel (`channels.get`), or `{ name }` to install what the name points at now. */\n channel: Pick<ChannelIface, 'hash'> | { name: string };\n connectorInstallId: string;\n /** What an agent gets in every chat this install creates. */\n agents: { provide: ProvideIface };\n /** Explicitly replace an existing install of the same connector. */\n replace?: boolean;\n /** Reaches only the channel's own code. */\n config?: Record<string, unknown>;\n}\n\nexport interface ProjectChannelsApiIface {\n publish: (args: PublishChannelArgsIface) => Promise<PublishChannelResponseIface>;\n get: (\n selector: ({ name: string } | { hash: string }) & SignalOptionsIface,\n ) => Promise<ChannelIface>;\n /** Fails with `requirements_unmet` unless `agents.provide` meets the answering agent's requirements. */\n install: (args: InstallChannelArgsIface) => Promise<CreateChannelBindingResponseIface>;\n}\n\nexport interface ChannelBindingsApiIface {\n places(args: { bindingId: string } & SignalOptionsIface): Promise<ChannelSeenPlaceIface[]>;\n routes(args: { conversationId: string } & SignalOptionsIface): Promise<ChannelRouteIface[]>;\n connect(\n args: ConnectChannelPlaceRequestIface & { conversationId: string } & SignalOptionsIface,\n ): Promise<{ id: string }>;\n disconnect(\n args: { conversationId: string; routeId: string } & SignalOptionsIface,\n ): Promise<{ ok: boolean }>;\n}\n\nconst channelsPath = (projectId: string, suffix: string): string =>\n `/v1/projects/${encodePath(projectId)}/channels${suffix}`;\n\nexport const createProjectChannelsApi = (args: {\n context: ClientContextIface;\n projectId: string;\n sourceOf: ChannelSourceOf;\n}): ProjectChannelsApiIface => {\n const { http } = args.context;\n return {\n publish: (publish) => {\n const source: ChannelSourceIface =\n 'channel' in publish\n ? args.sourceOf(publish.channel)\n : {\n source: publish.source,\n ...(publish.export == null ? {} : { export: publish.export }),\n };\n return http.request({\n method: HttpMethod.Post,\n path: channelsPath(args.projectId, '/publish'),\n body: {\n schema: publishChannelRequestSchema,\n value: { name: publish.name, ...source, visibility: publish.visibility },\n },\n response: publishChannelResponseSchema,\n signal: publish.signal,\n });\n },\n get: ({ signal, ...selector }) =>\n http.request({\n method: HttpMethod.Get,\n path: channelsPath(args.projectId, '/lookup'),\n query: {\n name: 'name' in selector ? selector.name : undefined,\n hash: 'hash' in selector ? selector.hash : undefined,\n },\n response: channelSchema,\n signal,\n }),\n install: (install) => {\n const channel =\n 'hash' in install.channel ? { hash: install.channel.hash } : { name: install.channel.name };\n return http.request({\n method: HttpMethod.Post,\n path: '/v1/channel-bindings',\n body: {\n schema: createChannelBindingRequestSchema,\n value: {\n projectId: args.projectId,\n channel,\n connectorInstallId: install.connectorInstallId,\n agents: { provide: provideDocumentOf(install.agents.provide) },\n replace: install.replace,\n config: install.config,\n },\n },\n response: createChannelBindingResponseSchema,\n signal: install.signal,\n });\n },\n };\n};\n\nexport const createChannelBindingsApi = (ctx: ClientContextIface): ChannelBindingsApiIface => ({\n places: async ({ bindingId, signal }) =>\n (\n await ctx.http.request({\n method: HttpMethod.Get,\n path: `/v1/channel-bindings/${encodePath(bindingId)}/places`,\n response: channelPlacesResponseSchema,\n signal,\n })\n ).places,\n routes: async ({ conversationId, signal }) =>\n (\n await ctx.http.request({\n method: HttpMethod.Get,\n path: `/v1/conversations/${encodePath(conversationId)}/channel-routes`,\n response: channelRoutesResponseSchema,\n signal,\n })\n ).routes,\n connect: ({ conversationId, signal, ...body }) =>\n ctx.http.request({\n method: HttpMethod.Post,\n path: `/v1/conversations/${encodePath(conversationId)}/channel-routes`,\n body: { schema: connectChannelPlaceRequestSchema, value: body },\n response: connectChannelPlaceResponseSchema,\n signal,\n }),\n disconnect: ({ conversationId, routeId, signal }) =>\n ctx.http.request({\n method: HttpMethod.Delete,\n path: `/v1/conversations/${encodePath(conversationId)}/channel-routes/${encodePath(routeId)}`,\n response: disconnectChannelRouteResponseSchema,\n signal,\n }),\n});\n\n/** The default `ChannelSourceOf` when no codec is available. */\nexport const noChannelSource: ChannelSourceOf = () => {\n throw clientError({\n message: 'Publish a channel as `source`: this build cannot capture a channel value',\n status: 0,\n code: ClientErrorCode.InvalidRequest,\n });\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }