@finalai/agents 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HOSTING.md +334 -245
- package/README.md +214 -29
- package/dist/modules/agent-client/agent-input.d.mts +24 -0
- package/dist/modules/agent-client/agent-input.mjs +46 -0
- package/dist/modules/agent-client/agent-input.mjs.map +7 -0
- package/dist/modules/agent-client/channels.d.mts +128 -16
- package/dist/modules/agent-client/channels.mjs +216 -33
- package/dist/modules/agent-client/channels.mjs.map +2 -2
- package/dist/modules/agent-client/client.d.mts +91 -21
- package/dist/modules/agent-client/client.mjs +79 -24
- package/dist/modules/agent-client/client.mjs.map +2 -2
- package/dist/modules/agent-client/config-options.mjs +1 -2
- package/dist/modules/agent-client/config-options.mjs.map +2 -2
- package/dist/modules/agent-client/conversation-resources.d.mts +102 -0
- package/dist/modules/agent-client/conversation-resources.mjs +178 -0
- package/dist/modules/agent-client/conversation-resources.mjs.map +7 -0
- package/dist/modules/agent-client/conversations.d.mts +120 -38
- package/dist/modules/agent-client/conversations.mjs +386 -71
- package/dist/modules/agent-client/conversations.mjs.map +2 -2
- package/dist/modules/agent-client/defaults.d.mts +8 -0
- package/dist/modules/agent-client/defaults.mjs +77 -0
- package/dist/modules/agent-client/defaults.mjs.map +7 -0
- package/dist/modules/agent-client/errors.d.mts +22 -2
- package/dist/modules/agent-client/errors.mjs +19 -0
- package/dist/modules/agent-client/errors.mjs.map +2 -2
- package/dist/modules/agent-client/events.d.mts +62 -0
- package/dist/modules/agent-client/events.mjs +107 -0
- package/dist/modules/agent-client/events.mjs.map +7 -0
- package/dist/modules/agent-client/harnesses.d.mts +66 -0
- package/dist/modules/agent-client/harnesses.mjs +156 -0
- package/dist/modules/agent-client/harnesses.mjs.map +7 -0
- package/dist/modules/agent-client/http.d.mts +2 -1
- package/dist/modules/agent-client/http.mjs +21 -2
- package/dist/modules/agent-client/http.mjs.map +2 -2
- package/dist/modules/agent-client/index.d.mts +21 -6
- package/dist/modules/agent-client/index.mjs +26 -0
- package/dist/modules/agent-client/index.mjs.map +2 -2
- package/dist/modules/agent-client/integrations.d.mts +40 -0
- package/dist/modules/agent-client/integrations.mjs +92 -0
- package/dist/modules/agent-client/integrations.mjs.map +7 -0
- package/dist/modules/agent-client/local-host-protocol.d.mts +156 -0
- package/dist/modules/agent-client/local-host-protocol.mjs +258 -0
- package/dist/modules/agent-client/local-host-protocol.mjs.map +7 -0
- package/dist/modules/agent-client/local-host.d.mts +56 -0
- package/dist/modules/agent-client/local-host.mjs +200 -0
- package/dist/modules/agent-client/local-host.mjs.map +7 -0
- package/dist/modules/agent-client/oauth-clients.d.mts +36 -0
- package/dist/modules/agent-client/oauth-clients.mjs +67 -0
- package/dist/modules/agent-client/oauth-clients.mjs.map +7 -0
- package/dist/modules/agent-client/project-agents.d.mts +54 -0
- package/dist/modules/agent-client/project-agents.mjs +111 -0
- package/dist/modules/agent-client/project-agents.mjs.map +7 -0
- package/dist/modules/agent-client/project.d.mts +48 -0
- package/dist/modules/agent-client/project.mjs +66 -0
- package/dist/modules/agent-client/project.mjs.map +7 -0
- package/dist/modules/agent-client/projects.d.mts +61 -0
- package/dist/modules/agent-client/projects.mjs +145 -0
- package/dist/modules/agent-client/projects.mjs.map +7 -0
- package/dist/modules/agent-client/provide.d.mts +41 -0
- package/dist/modules/agent-client/provide.mjs +90 -0
- package/dist/modules/agent-client/provide.mjs.map +7 -0
- package/dist/modules/agent-client/publishers.d.mts +57 -0
- package/dist/modules/agent-client/publishers.mjs +109 -0
- package/dist/modules/agent-client/publishers.mjs.map +7 -0
- package/dist/modules/agent-client/requirements.d.mts +60 -0
- package/dist/modules/agent-client/requirements.mjs +83 -0
- package/dist/modules/agent-client/requirements.mjs.map +7 -0
- package/dist/modules/agent-client/sandbox-providers.d.mts +34 -0
- package/dist/modules/agent-client/sandbox-providers.mjs +75 -0
- package/dist/modules/agent-client/sandbox-providers.mjs.map +7 -0
- package/dist/modules/agent-client/sandbox-uri.d.mts +1 -1
- package/dist/modules/agent-client/sandbox-uri.mjs +4 -4
- package/dist/modules/agent-client/sandbox-uri.mjs.map +1 -1
- package/dist/modules/agent-client/sandboxes.d.mts +72 -0
- package/dist/modules/agent-client/sandboxes.mjs +138 -0
- package/dist/modules/agent-client/sandboxes.mjs.map +7 -0
- package/dist/modules/agent-client/schedules.d.mts +9 -0
- package/dist/modules/agent-client/schedules.mjs +17 -0
- package/dist/modules/agent-client/schedules.mjs.map +7 -0
- package/dist/modules/agent-client/sessions.d.mts +46 -8
- package/dist/modules/agent-client/sessions.mjs +91 -29
- package/dist/modules/agent-client/sessions.mjs.map +2 -2
- package/dist/modules/agent-client/start.d.mts +101 -0
- package/dist/modules/agent-client/start.mjs +260 -0
- package/dist/modules/agent-client/start.mjs.map +7 -0
- package/dist/modules/agent-client/test-fakes.d.mts +1 -0
- package/dist/modules/agent-client/test-fakes.mjs +3 -1
- package/dist/modules/agent-client/test-fakes.mjs.map +2 -2
- package/dist/modules/cli/agent-module.d.mts +39 -0
- package/dist/modules/cli/agent-module.mjs +89 -0
- package/dist/modules/cli/agent-module.mjs.map +7 -0
- package/dist/modules/cli/cli.d.mts +6 -6
- package/dist/modules/cli/cli.mjs +94 -120
- package/dist/modules/cli/cli.mjs.map +2 -2
- package/dist/modules/cli/conformance.d.mts +2 -6
- package/dist/modules/cli/conformance.mjs +5 -8
- package/dist/modules/cli/conformance.mjs.map +2 -2
- package/dist/modules/cli/main.mjs.map +1 -1
- package/dist/modules/cli/output.d.mts +0 -9
- package/dist/modules/cli/output.mjs +7 -85
- package/dist/modules/cli/output.mjs.map +2 -2
- package/dist/modules/harnesses.mjs.map +2 -2
- package/dist/modules/index.d.mts +0 -2
- package/dist/modules/index.mjs +0 -4
- package/dist/modules/index.mjs.map +2 -2
- package/dist/modules/integrations.d.mts +24 -0
- package/dist/modules/integrations.mjs +30 -0
- package/dist/modules/integrations.mjs.map +7 -0
- package/dist/modules/public.d.mts +10 -10
- package/dist/modules/public.mjs +29 -78
- package/dist/modules/public.mjs.map +2 -2
- package/dist/modules/sandboxes.d.mts +2 -0
- package/dist/modules/sandboxes.mjs +4 -0
- package/dist/modules/sandboxes.mjs.map +2 -2
- package/dist/modules/verify.d.mts +1 -0
- package/dist/modules/verify.mjs +2 -0
- package/dist/modules/verify.mjs.map +7 -0
- package/dist/modules/webhooks.d.mts +37 -0
- package/dist/modules/webhooks.mjs +100 -0
- package/dist/modules/webhooks.mjs.map +7 -0
- package/examples/release-scout/README.md +18 -10
- package/examples/release-scout/agent.ts +41 -0
- package/examples/release-scout/by-name.ts +43 -0
- package/examples/release-scout/db.ts +6 -0
- package/examples/release-scout/instructions.md +5 -0
- package/examples/release-scout/run-on-a-computer.ts +49 -0
- package/examples/release-scout/run.ts +38 -0
- package/package.json +37 -28
- package/dist/modules/agent-client/build.d.mts +0 -110
- package/dist/modules/agent-client/build.mjs +0 -213
- package/dist/modules/agent-client/build.mjs.map +0 -7
- package/dist/modules/authoring/final-channel.d.mts +0 -1
- package/dist/modules/authoring/final-channel.mjs +0 -2
- package/dist/modules/authoring/final-channel.mjs.map +0 -7
- package/dist/modules/authoring/index.d.mts +0 -1
- package/dist/modules/authoring/index.mjs +0 -2
- package/dist/modules/authoring/index.mjs.map +0 -7
- package/dist/modules/authoring/instructions.d.mts +0 -1
- package/dist/modules/authoring/instructions.mjs +0 -2
- package/dist/modules/authoring/instructions.mjs.map +0 -7
- package/dist/modules/authoring/providers.d.mts +0 -2
- package/dist/modules/authoring/providers.mjs +0 -1
- package/dist/modules/authoring/providers.mjs.map +0 -7
- package/dist/modules/cli/build.d.mts +0 -22
- package/dist/modules/cli/build.mjs +0 -77
- package/dist/modules/cli/build.mjs.map +0 -7
- package/dist/modules/cli/channel-install.d.mts +0 -12
- package/dist/modules/cli/channel-install.mjs +0 -25
- package/dist/modules/cli/channel-install.mjs.map +0 -7
- package/dist/modules/cli/channel-socket.d.mts +0 -9
- package/dist/modules/cli/channel-socket.mjs +0 -114
- package/dist/modules/cli/channel-socket.mjs.map +0 -7
- package/dist/modules/cli/dev.d.mts +0 -26
- package/dist/modules/cli/dev.mjs +0 -311
- package/dist/modules/cli/dev.mjs.map +0 -7
- package/dist/modules/cli/files.d.mts +0 -18
- package/dist/modules/cli/files.mjs +0 -66
- package/dist/modules/cli/files.mjs.map +0 -7
- package/dist/modules/cli/harness-descriptions.d.mts +0 -20
- package/dist/modules/cli/harness-descriptions.mjs +0 -70
- package/dist/modules/cli/harness-descriptions.mjs.map +0 -7
- package/dist/modules/cli/publish.d.mts +0 -15
- package/dist/modules/cli/publish.mjs +0 -92
- package/dist/modules/cli/publish.mjs.map +0 -7
- package/dist/modules/compile.d.mts +0 -3
- package/dist/modules/compile.mjs +0 -58
- package/dist/modules/compile.mjs.map +0 -7
- package/dist/modules/index.browser.d.mts +0 -4
- package/dist/modules/index.browser.mjs +0 -8
- package/dist/modules/index.browser.mjs.map +0 -7
- package/examples/custom-harness/README.md +0 -16
- package/examples/custom-harness/agent.ts +0 -154
- package/examples/custom-sandbox/README.md +0 -12
- package/examples/custom-sandbox/agent.ts +0 -14
- package/examples/custom-sandbox/sandbox.ts +0 -24
- package/examples/release-scout/agent/agent.ts +0 -22
- package/examples/release-scout/agent/channels/github-signature.ts +0 -27
- package/examples/release-scout/agent/channels/github.ts +0 -32
- package/examples/release-scout/agent/connections/linear.ts +0 -9
- package/examples/release-scout/agent/hooks/audit.ts +0 -24
- package/examples/release-scout/agent/instructions/org-context.ts +0 -26
- package/examples/release-scout/agent/instructions.md +0 -2
- package/examples/release-scout/agent/sandbox.ts +0 -20
- package/examples/release-scout/agent/schedules/daily-digest.md +0 -7
- package/examples/release-scout/agent/skills/triage/SKILL.md +0 -8
- package/examples/release-scout/agent/skills/triage/checklist.md +0 -3
- package/examples/release-scout/agent/tools/lookup_release_notes.ts +0 -24
- 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
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
9
|
-
import {
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
25
|
-
which order. Set the payer policy explicitly in the harness configuration.
|
|
80
|
+
## Requirements and `provide`
|
|
26
81
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
`
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,23 +1,135 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { type ClientContextIface, type SignalOptionsIface } from "./context.mjs";
|
|
1
|
+
import { type ActorInputIface, type ChannelAppIface, type ChannelBindingIface, type ChannelIdentityLinkIface, type ChannelIdentityLinkProgressIface, type ChannelIface, type ChannelSeenPlaceIface, type ChannelTenantTicketIface, type ChannelTicketIface, type CompleteChannelIdentityLinkRequestIface, type CompleteChannelPlaceConnectionRequestIface, type CreateChannelAppRequestIface, type DefinitionVisibility, type InstallChannelRequestIface, type InstalledChannelIface, type PublishChannelResponseIface, type UpdateChannelAppRequestIface, type UpdateChannelBindingRequestIface } 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
|
+
/** A channel app of this project that installs of the publication use unless they bring their own. */
|
|
16
|
+
app?: string;
|
|
17
|
+
} & SignalOptionsIface & ({
|
|
18
|
+
channel: object;
|
|
19
|
+
} | {
|
|
20
|
+
source: string;
|
|
21
|
+
export?: string;
|
|
22
|
+
});
|
|
23
|
+
export type InstallChannelArgsIface = Omit<InstallChannelRequestIface, 'agents'> & {
|
|
24
|
+
/** What the agent gets in every chat this install creates. */
|
|
25
|
+
agents: {
|
|
26
|
+
provide: ProvideIface;
|
|
27
|
+
};
|
|
28
|
+
} & SignalOptionsIface;
|
|
29
|
+
export type UpdateChannelBindingArgsIface = Omit<UpdateChannelBindingRequestIface, 'agents'> & {
|
|
30
|
+
bindingId: string;
|
|
31
|
+
agents?: {
|
|
32
|
+
provide: ProvideIface;
|
|
33
|
+
};
|
|
34
|
+
} & SignalOptionsIface;
|
|
35
|
+
export interface ProjectChannelsApiIface {
|
|
36
|
+
publish: (args: PublishChannelArgsIface) => Promise<PublishChannelResponseIface>;
|
|
37
|
+
get: (selector: ({
|
|
38
|
+
name: string;
|
|
39
|
+
} | {
|
|
40
|
+
hash: string;
|
|
41
|
+
}) & SignalOptionsIface) => Promise<ChannelIface>;
|
|
42
|
+
/**
|
|
43
|
+
* Installs a channel in the project. Fails with `requirements_unmet`, and
|
|
44
|
+
* installs nothing, unless `agents.provide` meets the agent's requirements
|
|
45
|
+
* and the channel's app requirement is met.
|
|
46
|
+
*/
|
|
47
|
+
install: (args: InstallChannelArgsIface) => Promise<InstalledChannelIface>;
|
|
48
|
+
/** The project's installs, newest first. */
|
|
49
|
+
installs: (options?: SignalOptionsIface & {
|
|
50
|
+
includeArchived?: boolean;
|
|
51
|
+
}) => Promise<ChannelBindingIface[]>;
|
|
52
|
+
}
|
|
3
53
|
export interface ChannelBindingsApiIface {
|
|
4
|
-
|
|
5
|
-
|
|
54
|
+
/** One install, with whether its agent's requirements are met now. */
|
|
55
|
+
get: (args: {
|
|
6
56
|
bindingId: string;
|
|
7
|
-
} & SignalOptionsIface)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} & SignalOptionsIface)
|
|
14
|
-
|
|
57
|
+
} & SignalOptionsIface) => Promise<ChannelBindingIface>;
|
|
58
|
+
/** Fails with `revision_conflict` unless `revision` is the one last read, and with `requirements_unmet` when the change would leave them unmet. */
|
|
59
|
+
update: (args: UpdateChannelBindingArgsIface) => Promise<InstalledChannelIface>;
|
|
60
|
+
/** Ends the install: its connected places, tenants, listeners and the links made through it. */
|
|
61
|
+
uninstall: (args: {
|
|
62
|
+
bindingId: string;
|
|
63
|
+
} & SignalOptionsIface) => Promise<{
|
|
64
|
+
archivedAt: string | null;
|
|
15
65
|
}>;
|
|
16
|
-
|
|
17
|
-
|
|
66
|
+
/** A single-use link that installs the provider app for one tenant (a workspace, a server). */
|
|
67
|
+
tenantTicket: (args: {
|
|
68
|
+
bindingId: string;
|
|
69
|
+
} & SignalOptionsIface) => Promise<ChannelTenantTicketIface>;
|
|
70
|
+
/** The provider places the install has seen. */
|
|
71
|
+
places: (args: {
|
|
72
|
+
bindingId: string;
|
|
73
|
+
} & SignalOptionsIface) => Promise<ChannelSeenPlaceIface[]>;
|
|
74
|
+
}
|
|
75
|
+
export interface ChannelAppsApiIface {
|
|
76
|
+
/** Registers the provider application's credentials; secret values stay project secrets. */
|
|
77
|
+
create: (args: CreateChannelAppRequestIface & SignalOptionsIface) => Promise<ChannelAppIface>;
|
|
78
|
+
/** The apps of the project and its ancestors. */
|
|
79
|
+
list: (options?: SignalOptionsIface) => Promise<ChannelAppIface[]>;
|
|
80
|
+
update: (args: UpdateChannelAppRequestIface & {
|
|
81
|
+
id: string;
|
|
82
|
+
} & SignalOptionsIface) => Promise<ChannelAppIface>;
|
|
83
|
+
/** Refused while a live install or publication uses the app. */
|
|
84
|
+
delete: (args: {
|
|
85
|
+
id: string;
|
|
86
|
+
} & SignalOptionsIface) => Promise<void>;
|
|
87
|
+
}
|
|
88
|
+
/** The actor an API key or app acts for, by its external id. */
|
|
89
|
+
export interface ActorOptionIface {
|
|
90
|
+
actor?: string;
|
|
91
|
+
}
|
|
92
|
+
export interface ChannelTicketsApiIface {
|
|
93
|
+
/** What a ticket from an installer's link or connect page is for. */
|
|
94
|
+
get: (args: {
|
|
95
|
+
ticket: string;
|
|
96
|
+
} & ActorOptionIface & SignalOptionsIface) => Promise<ChannelTicketIface>;
|
|
97
|
+
/** Links the ticket's channel account to the caller's person, or to `actor`. */
|
|
98
|
+
link: (args: {
|
|
99
|
+
ticket: string;
|
|
100
|
+
} & CompleteChannelIdentityLinkRequestIface & SignalOptionsIface) => Promise<ChannelIdentityLinkProgressIface>;
|
|
101
|
+
/** Connects the ticket's place to a conversation the caller manages. */
|
|
102
|
+
connect: (args: {
|
|
103
|
+
ticket: string;
|
|
104
|
+
} & CompleteChannelPlaceConnectionRequestIface & SignalOptionsIface) => Promise<{
|
|
18
105
|
routeId: string;
|
|
19
|
-
} & SignalOptionsIface): Promise<{
|
|
20
|
-
ok: boolean;
|
|
21
106
|
}>;
|
|
22
107
|
}
|
|
108
|
+
export interface IdentityLinksApiIface {
|
|
109
|
+
/** The channel accounts linked to the caller's person, or to `actor`. */
|
|
110
|
+
list: (options?: ActorOptionIface & SignalOptionsIface) => Promise<ChannelIdentityLinkIface[]>;
|
|
111
|
+
/** Chooses where the person's direct messages to the channel land. */
|
|
112
|
+
update: (args: {
|
|
113
|
+
id: string;
|
|
114
|
+
directConversationId: string | null;
|
|
115
|
+
actor?: ActorInputIface;
|
|
116
|
+
} & SignalOptionsIface) => Promise<void>;
|
|
117
|
+
/** Unlinks the account. */
|
|
118
|
+
delete: (args: {
|
|
119
|
+
id: string;
|
|
120
|
+
} & ActorOptionIface & SignalOptionsIface) => Promise<void>;
|
|
121
|
+
}
|
|
122
|
+
export declare const createProjectChannelsApi: (args: {
|
|
123
|
+
context: ClientContextIface;
|
|
124
|
+
projectId: string;
|
|
125
|
+
sourceOf: ChannelSourceOf;
|
|
126
|
+
}) => ProjectChannelsApiIface;
|
|
23
127
|
export declare const createChannelBindingsApi: (ctx: ClientContextIface) => ChannelBindingsApiIface;
|
|
128
|
+
export declare const createChannelAppsApi: (args: {
|
|
129
|
+
context: ClientContextIface;
|
|
130
|
+
projectId: string;
|
|
131
|
+
}) => ChannelAppsApiIface;
|
|
132
|
+
export declare const createChannelTicketsApi: (ctx: ClientContextIface) => ChannelTicketsApiIface;
|
|
133
|
+
export declare const createIdentityLinksApi: (ctx: ClientContextIface) => IdentityLinksApiIface;
|
|
134
|
+
/** The default `ChannelSourceOf` when no codec is available. */
|
|
135
|
+
export declare const noChannelSource: ChannelSourceOf;
|