@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.
- 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 +52 -3
- package/dist/modules/agent-client/channels.mjs +71 -10
- package/dist/modules/agent-client/channels.mjs.map +2 -2
- package/dist/modules/agent-client/client.d.mts +85 -20
- package/dist/modules/agent-client/client.mjs +74 -21
- 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 +85 -0
- package/dist/modules/agent-client/conversation-resources.mjs +150 -0
- package/dist/modules/agent-client/conversation-resources.mjs.map +7 -0
- package/dist/modules/agent-client/conversations.d.mts +116 -38
- package/dist/modules/agent-client/conversations.mjs +379 -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 +43 -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 +65 -0
- package/dist/modules/agent-client/sandboxes.mjs +130 -0
- package/dist/modules/agent-client/sandboxes.mjs.map +7 -0
- package/dist/modules/agent-client/schedules.d.mts +24 -0
- package/dist/modules/agent-client/schedules.mjs +56 -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 +42 -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/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
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { jsonValueSchema, PROCESS_CAPABILITIES, RuntimeKind } from "@finalai/agent-protocol";
|
|
2
|
+
import {
|
|
3
|
+
harnessCheckRequestSchema,
|
|
4
|
+
harnessCheckResponseSchema,
|
|
5
|
+
harnessDefinitionInfoSchema,
|
|
6
|
+
storeAgentDocumentRequestSchema,
|
|
7
|
+
storeAgentDocumentResponseSchema
|
|
8
|
+
} from "@finalai/agent-protocol/agent-platform";
|
|
9
|
+
import {
|
|
10
|
+
resolveAgentInput
|
|
11
|
+
} from "./agent-input.mjs";
|
|
12
|
+
import { workers } from "@finalai/final-agent-provider/sandboxes";
|
|
13
|
+
import { encodePath } from "./context.mjs";
|
|
14
|
+
import { clientError, ClientErrorCode, isClientError } from "./errors.mjs";
|
|
15
|
+
import { HttpMethod } from "./http.mjs";
|
|
16
|
+
import {
|
|
17
|
+
openLocalHost
|
|
18
|
+
} from "./local-host.mjs";
|
|
19
|
+
import { LocalHostOwnerKind } from "./local-host-protocol.mjs";
|
|
20
|
+
import { layerProvide, provideDocumentOf } from "./provide.mjs";
|
|
21
|
+
import { assertRequirementsMet, capabilitiesToServeLocally } from "./requirements.mjs";
|
|
22
|
+
import { createSandboxesApi } from "./sandboxes.mjs";
|
|
23
|
+
const LOCAL_PLACEHOLDER = "local-host";
|
|
24
|
+
const lookupHarness = async (args) => {
|
|
25
|
+
if (args.harness.environment != null) return null;
|
|
26
|
+
try {
|
|
27
|
+
return await args.context.http.request({
|
|
28
|
+
method: HttpMethod.Get,
|
|
29
|
+
path: `/v1/projects/${encodePath(args.projectId)}/harnesses/lookup`,
|
|
30
|
+
query: { name: args.harness.harness },
|
|
31
|
+
response: harnessDefinitionInfoSchema,
|
|
32
|
+
signal: args.signal
|
|
33
|
+
});
|
|
34
|
+
} catch (cause) {
|
|
35
|
+
if (isClientError(cause) && cause.status === 404) return null;
|
|
36
|
+
throw cause;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const IDEMPOTENCY_KEY_MAX = 200;
|
|
40
|
+
const WORKERS_KEY_SUFFIX = ":workers";
|
|
41
|
+
const workersKeyOf = async (owner) => {
|
|
42
|
+
const plain = `${owner.kind}:${owner.id}`;
|
|
43
|
+
if (plain.length + WORKERS_KEY_SUFFIX.length <= IDEMPOTENCY_KEY_MAX)
|
|
44
|
+
return `${plain}${WORKERS_KEY_SUFFIX}`;
|
|
45
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(plain));
|
|
46
|
+
const hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0"));
|
|
47
|
+
return `sha256:${hex.join("")}${WORKERS_KEY_SUFFIX}`;
|
|
48
|
+
};
|
|
49
|
+
const withWorkersEnvironment = async (args) => {
|
|
50
|
+
const info = await lookupHarness(args);
|
|
51
|
+
const native = info?.native ?? [];
|
|
52
|
+
if (info == null || native.length > 0 || !info.runtimes.includes(RuntimeKind.Worker))
|
|
53
|
+
return { harness: args.harness, ownerId: args.owner.id, created: null, native };
|
|
54
|
+
const chosen = args.owner.id == null || args.ownerIdReserved === true;
|
|
55
|
+
const ownerId = args.owner.id ?? args.context.newKey();
|
|
56
|
+
const sandbox = await createSandboxesApi({
|
|
57
|
+
context: args.context,
|
|
58
|
+
projectId: args.projectId
|
|
59
|
+
}).create(workers(), {
|
|
60
|
+
ownedBy: args.owner.kind === LocalHostOwnerKind.Session ? { session: ownerId } : { conversation: ownerId },
|
|
61
|
+
idempotencyKey: await workersKeyOf({ kind: args.owner.kind, id: ownerId }),
|
|
62
|
+
signal: args.signal
|
|
63
|
+
});
|
|
64
|
+
const ownerPath = args.owner.kind === LocalHostOwnerKind.Session ? `/v1/sessions/${encodePath(ownerId)}` : `/v1/conversations/${encodePath(ownerId)}`;
|
|
65
|
+
const discard = async () => {
|
|
66
|
+
const created = await args.context.http.request({ method: HttpMethod.Get, path: ownerPath, response: jsonValueSchema }).then(
|
|
67
|
+
() => true,
|
|
68
|
+
(cause) => !(isClientError(cause) && cause.status === 404)
|
|
69
|
+
);
|
|
70
|
+
if (!created) await sandbox.delete();
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
harness: { ...args.harness, environment: sandbox.id },
|
|
74
|
+
ownerId,
|
|
75
|
+
created: chosen ? { discard } : null,
|
|
76
|
+
native
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
const storeDocument = async (deps, projectId, agent, signal) => {
|
|
80
|
+
if (agent.ref.document == null) return;
|
|
81
|
+
await deps.context.http.request({
|
|
82
|
+
method: HttpMethod.Put,
|
|
83
|
+
path: `/v1/projects/${encodePath(projectId)}/agents/documents`,
|
|
84
|
+
body: {
|
|
85
|
+
schema: storeAgentDocumentRequestSchema,
|
|
86
|
+
value: { document: agent.ref.document, hash: agent.hash }
|
|
87
|
+
},
|
|
88
|
+
response: storeAgentDocumentResponseSchema,
|
|
89
|
+
signal
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
const checkHarness = (args) => args.context.http.request({
|
|
93
|
+
method: HttpMethod.Post,
|
|
94
|
+
path: `/v1/projects/${encodePath(args.projectId)}/harnesses/check`,
|
|
95
|
+
body: {
|
|
96
|
+
schema: harnessCheckRequestSchema,
|
|
97
|
+
value: {
|
|
98
|
+
agent: args.hash,
|
|
99
|
+
harness: args.harness,
|
|
100
|
+
...args.compute == null ? {} : { compute: args.compute }
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
response: harnessCheckResponseSchema,
|
|
104
|
+
signal: args.signal
|
|
105
|
+
});
|
|
106
|
+
const startAgent = async (deps, args) => {
|
|
107
|
+
deps.context.closeSignal.throwIfAborted();
|
|
108
|
+
const agent = await resolveAgentInput(args.agent, deps.codec);
|
|
109
|
+
const own = provideDocumentOf(args.provide);
|
|
110
|
+
const effective = layerProvide(own, args.shared ?? null);
|
|
111
|
+
const codeMissing = agent.inProcess.length > 0 && agent.code == null;
|
|
112
|
+
if (effective.harness == null || args.projectId == null || codeMissing)
|
|
113
|
+
return startResolved(deps, { args, agent, own, ownerId: args.owner.id });
|
|
114
|
+
const placed = await withWorkersEnvironment({
|
|
115
|
+
context: deps.context,
|
|
116
|
+
projectId: args.projectId,
|
|
117
|
+
harness: effective.harness,
|
|
118
|
+
owner: args.owner,
|
|
119
|
+
ownerIdReserved: args.ownerIdReserved,
|
|
120
|
+
signal: args.signal
|
|
121
|
+
});
|
|
122
|
+
if (placed.harness === effective.harness)
|
|
123
|
+
return startResolved(deps, {
|
|
124
|
+
args,
|
|
125
|
+
agent,
|
|
126
|
+
own,
|
|
127
|
+
ownerId: args.owner.id,
|
|
128
|
+
harnessNative: placed.native.length > 0
|
|
129
|
+
});
|
|
130
|
+
const undo = () => {
|
|
131
|
+
void placed.created?.discard().catch(() => void 0);
|
|
132
|
+
};
|
|
133
|
+
try {
|
|
134
|
+
const started = await startResolved(deps, {
|
|
135
|
+
args,
|
|
136
|
+
agent,
|
|
137
|
+
own: { ...own, harness: placed.harness },
|
|
138
|
+
ownerId: placed.ownerId
|
|
139
|
+
});
|
|
140
|
+
return {
|
|
141
|
+
...started,
|
|
142
|
+
abandon: () => {
|
|
143
|
+
started.abandon();
|
|
144
|
+
undo();
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
} catch (cause) {
|
|
148
|
+
undo();
|
|
149
|
+
throw cause;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
const startResolved = async (deps, resolved) => {
|
|
153
|
+
const { args, agent, own, ownerId } = resolved;
|
|
154
|
+
const closeSignal = deps.context.closeSignal;
|
|
155
|
+
const signal = args.signal == null ? closeSignal : AbortSignal.any([args.signal, closeSignal]);
|
|
156
|
+
const effective = layerProvide(own, args.shared ?? null);
|
|
157
|
+
let ref = agent.ref;
|
|
158
|
+
let unserved = capabilitiesToServeLocally({ agent, provide: effective, harness: null });
|
|
159
|
+
const mayHostHarness = resolved.harnessNative === true && deps.localCompute && effective.harness?.environment == null && !PROCESS_CAPABILITIES.some((capability) => effective.compute?.[capability] != null);
|
|
160
|
+
let harness = null;
|
|
161
|
+
if ((unserved.length > 0 || mayHostHarness) && effective.harness != null && args.projectId != null) {
|
|
162
|
+
await storeDocument(deps, args.projectId, agent, args.signal);
|
|
163
|
+
ref = { hash: agent.hash };
|
|
164
|
+
harness = await checkHarness({
|
|
165
|
+
context: deps.context,
|
|
166
|
+
projectId: args.projectId,
|
|
167
|
+
hash: agent.hash,
|
|
168
|
+
harness: effective.harness,
|
|
169
|
+
compute: effective.compute,
|
|
170
|
+
signal: args.signal
|
|
171
|
+
});
|
|
172
|
+
unserved = capabilitiesToServeLocally({ agent, provide: effective, harness });
|
|
173
|
+
}
|
|
174
|
+
const local = deps.localCompute ? unserved : [];
|
|
175
|
+
const servesCode = agent.code != null && agent.inProcess.length > 0;
|
|
176
|
+
const planned = {
|
|
177
|
+
...effective,
|
|
178
|
+
compute: {
|
|
179
|
+
...effective.compute,
|
|
180
|
+
...Object.fromEntries(local.map((capability) => [capability, LOCAL_PLACEHOLDER]))
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
assertRequirementsMet({ agent, provide: planned, harness, servesCode });
|
|
184
|
+
if (local.length === 0 && !servesCode)
|
|
185
|
+
return {
|
|
186
|
+
ref,
|
|
187
|
+
provide: own,
|
|
188
|
+
ownerId,
|
|
189
|
+
host: null,
|
|
190
|
+
abandon: () => void 0,
|
|
191
|
+
established: () => void 0
|
|
192
|
+
};
|
|
193
|
+
if (args.projectId == null)
|
|
194
|
+
throw clientError({
|
|
195
|
+
message: "Serving compute or in-process code from this process needs a project: use client.project({ id })",
|
|
196
|
+
status: 0,
|
|
197
|
+
code: ClientErrorCode.InvalidRequest
|
|
198
|
+
});
|
|
199
|
+
const host = await openLocalHost({
|
|
200
|
+
dial: deps.dial,
|
|
201
|
+
projectId: args.projectId,
|
|
202
|
+
owner: { ...args.owner, id: ownerId },
|
|
203
|
+
agent,
|
|
204
|
+
capabilities: local,
|
|
205
|
+
compute: deps.compute,
|
|
206
|
+
signal
|
|
207
|
+
});
|
|
208
|
+
if (closeSignal.aborted) {
|
|
209
|
+
host.close();
|
|
210
|
+
closeSignal.throwIfAborted();
|
|
211
|
+
}
|
|
212
|
+
deps.hosts.add(host);
|
|
213
|
+
void host.closed.then(() => deps.hosts.delete(host));
|
|
214
|
+
const sandboxId = host.sandboxId;
|
|
215
|
+
const provide = local.length === 0 || sandboxId == null ? own : {
|
|
216
|
+
...own,
|
|
217
|
+
compute: {
|
|
218
|
+
...effective.compute,
|
|
219
|
+
...Object.fromEntries(local.map((capability) => [capability, sandboxId]))
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
return {
|
|
223
|
+
ref,
|
|
224
|
+
provide,
|
|
225
|
+
ownerId: host.ownerId,
|
|
226
|
+
host,
|
|
227
|
+
abandon: () => host.close(),
|
|
228
|
+
established: () => host.established()
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
const serveCodeFor = async (deps, args) => {
|
|
232
|
+
const closeSignal = deps.context.closeSignal;
|
|
233
|
+
closeSignal.throwIfAborted();
|
|
234
|
+
const agent = await resolveAgentInput(args.agent, deps.codec);
|
|
235
|
+
if (agent.code == null || agent.inProcess.length === 0) return null;
|
|
236
|
+
const host = await openLocalHost({
|
|
237
|
+
dial: deps.dial,
|
|
238
|
+
projectId: args.projectId,
|
|
239
|
+
owner: args.owner,
|
|
240
|
+
agent,
|
|
241
|
+
capabilities: [],
|
|
242
|
+
compute: deps.compute,
|
|
243
|
+
signal: args.signal == null ? closeSignal : AbortSignal.any([args.signal, closeSignal])
|
|
244
|
+
});
|
|
245
|
+
if (closeSignal.aborted) {
|
|
246
|
+
host.close();
|
|
247
|
+
closeSignal.throwIfAborted();
|
|
248
|
+
}
|
|
249
|
+
deps.hosts.add(host);
|
|
250
|
+
void host.closed.then(() => deps.hosts.delete(host));
|
|
251
|
+
host.established();
|
|
252
|
+
return host;
|
|
253
|
+
};
|
|
254
|
+
export {
|
|
255
|
+
checkHarness,
|
|
256
|
+
serveCodeFor,
|
|
257
|
+
startAgent,
|
|
258
|
+
withWorkersEnvironment
|
|
259
|
+
};
|
|
260
|
+
//# sourceMappingURL=start.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/agent-client/start.ts"],
|
|
4
|
+
"sourcesContent": ["import { jsonValueSchema, PROCESS_CAPABILITIES, RuntimeKind } from '@finalai/agent-protocol';\nimport {\n harnessCheckRequestSchema,\n harnessCheckResponseSchema,\n harnessDefinitionInfoSchema,\n storeAgentDocumentRequestSchema,\n storeAgentDocumentResponseSchema,\n type AgentRefInputIface,\n type HarnessCheckResponseIface,\n type HarnessDefinitionInfoIface,\n type ProvideDocumentIface,\n} from '@finalai/agent-protocol/agent-platform';\nimport {\n resolveAgentInput,\n type AgentValueCodecIface,\n type ResolvedAgentIface,\n} from \"./agent-input.mjs\";\nimport { workers } from '@finalai/final-agent-provider/sandboxes';\nimport { encodePath, type ClientContextIface } from \"./context.mjs\";\nimport { clientError, ClientErrorCode, isClientError } from \"./errors.mjs\";\nimport { HttpMethod } from \"./http.mjs\";\nimport {\n openLocalHost,\n type LocalComputeIface,\n type LocalHostIface,\n type LocalHostSocketIface,\n} from \"./local-host.mjs\";\nimport { LocalHostOwnerKind, type LocalHostOwnerIface } from \"./local-host-protocol.mjs\";\nimport { layerProvide, provideDocumentOf, type ProvideIface } from \"./provide.mjs\";\nimport { assertRequirementsMet, capabilitiesToServeLocally } from \"./requirements.mjs\";\nimport { createSandboxesApi } from \"./sandboxes.mjs\";\n\n// Everything that happens before a call that starts an agent is sent: the\n// agent becomes its wire ref, handles become ids, a harness that runs only as\n// a worker program and names no environment gets a Workers sandbox the\n// session or conversation owns, the SDK runs the platform's requirements\n// check, and (unless turned off) this process provides the files and shell\n// the caller left out, over a local host connection that also answers the\n// agent's in-process code.\n\n/** What the project client needs to start agents; built once per client. */\nexport interface AgentStartDepsIface {\n context: ClientContextIface;\n codec: AgentValueCodecIface;\n /** False: never serve compute from this process (`createClient({ localCompute: false })`). */\n localCompute: boolean;\n compute: LocalComputeIface;\n dial: (path: string, signal?: AbortSignal) => Promise<LocalHostSocketIface>;\n /** Every open local host, so `client.close()` ends them. */\n hosts: Set<LocalHostIface>;\n}\n\nexport interface StartAgentArgsIface {\n projectId: string | null;\n agent: unknown;\n provide: ProvideIface;\n /** Provided alongside by a conversation; the participant's own wins each top-level key whole. */\n shared?: ProvideDocumentIface | null;\n owner: LocalHostOwnerIface;\n /** The owner id was reserved for this call (by a local host), not chosen by the caller. */\n ownerIdReserved?: boolean;\n signal?: AbortSignal;\n}\n\nexport interface StartedAgentIface {\n ref: AgentRefInputIface;\n /** The participant's or session's own provide, with this process's compute filled in. */\n provide: ProvideDocumentIface;\n /** The owner id, when a local host reserved or confirmed one, or the SDK chose one for a Workers sandbox. */\n ownerId: string | undefined;\n host: LocalHostIface | null;\n /**\n * Ends the local host when the call that would have used it failed, and\n * deletes a Workers sandbox created for an owner id the SDK chose once the\n * owner is confirmed not to exist.\n */\n abandon: () => void;\n /** The call that uses it succeeded: the local host stops keeping the process alive while idle. */\n established: () => void;\n}\n\nconst LOCAL_PLACEHOLDER = 'local-host';\n\n// Whether harness settings run in a Workers sandbox the caller left to the\n// SDK: they name no environment, and the harness runs only as a worker program\n// (it uses no files or shell natively, which would place it where `shell` is\n// provided). A name the project cannot resolve is left to the platform to refuse.\n// The harness's published definition, for settings that name no environment;\n// null when they name one or the platform knows no such harness.\nconst lookupHarness = async (args: {\n context: ClientContextIface;\n projectId: string;\n harness: NonNullable<ProvideDocumentIface['harness']>;\n signal: AbortSignal | undefined;\n}): Promise<HarnessDefinitionInfoIface | null> => {\n if (args.harness.environment != null) return null;\n try {\n return await args.context.http.request({\n method: HttpMethod.Get,\n path: `/v1/projects/${encodePath(args.projectId)}/harnesses/lookup`,\n query: { name: args.harness.harness },\n response: harnessDefinitionInfoSchema,\n signal: args.signal,\n });\n } catch (cause) {\n if (isClientError(cause) && cause.status === 404) return null;\n throw cause;\n }\n};\n\nconst IDEMPOTENCY_KEY_MAX = 200;\nconst WORKERS_KEY_SUFFIX = ':workers';\n\n// One Workers sandbox per owner: `<owner kind>:<owner id>:workers` (a session and a\n// conversation may share a caller-chosen id), or a digest of that when too long.\nconst workersKeyOf = async (owner: { kind: string; id: string }): Promise<string> => {\n const plain = `${owner.kind}:${owner.id}`;\n if (plain.length + WORKERS_KEY_SUFFIX.length <= IDEMPOTENCY_KEY_MAX)\n return `${plain}${WORKERS_KEY_SUFFIX}`;\n const digest = await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(plain));\n const hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0'));\n return `sha256:${hex.join('')}${WORKERS_KEY_SUFFIX}`;\n};\n\nexport interface WorkersEnvironmentIface {\n /** The harness settings with the Workers sandbox as their environment; unchanged when none was needed. */\n harness: NonNullable<ProvideDocumentIface['harness']>;\n /** The owner id the sandbox was created for: the caller's, else one the SDK chose. */\n ownerId: string | undefined;\n /**\n * When the SDK chose the owner id: deletes the sandbox unless its owner was\n * created after all (a lost response does not prove the creation failed).\n */\n created: { discard: () => Promise<void> } | null;\n /**\n * Capabilities the harness uses natively from where it runs, when its\n * settings name no environment; such a harness runs where `shell` is.\n */\n native: readonly string[];\n}\n\n/**\n * Gives harness settings that name no environment, for a harness that runs\n * only as a worker program, a Workers sandbox owned by the session or\n * conversation: the same one on a retry with the same owner id. A caller that\n * chose no owner id gets one chosen here, which the session or conversation\n * must then be created with.\n */\nexport const withWorkersEnvironment = async (args: {\n context: ClientContextIface;\n projectId: string;\n harness: NonNullable<ProvideDocumentIface['harness']>;\n owner: LocalHostOwnerIface;\n /** The owner id was reserved for this call, not chosen by the caller. */\n ownerIdReserved?: boolean;\n signal: AbortSignal | undefined;\n}): Promise<WorkersEnvironmentIface> => {\n const info = await lookupHarness(args);\n const native = info?.native ?? [];\n if (info == null || native.length > 0 || !info.runtimes.includes(RuntimeKind.Worker))\n return { harness: args.harness, ownerId: args.owner.id, created: null, native };\n const chosen = args.owner.id == null || args.ownerIdReserved === true;\n const ownerId = args.owner.id ?? args.context.newKey();\n const sandbox = await createSandboxesApi({\n context: args.context,\n projectId: args.projectId,\n }).create(workers(), {\n ownedBy:\n args.owner.kind === LocalHostOwnerKind.Session\n ? { session: ownerId }\n : { conversation: ownerId },\n idempotencyKey: await workersKeyOf({ kind: args.owner.kind, id: ownerId }),\n signal: args.signal,\n });\n const ownerPath =\n args.owner.kind === LocalHostOwnerKind.Session\n ? `/v1/sessions/${encodePath(ownerId)}`\n : `/v1/conversations/${encodePath(ownerId)}`;\n const discard = async (): Promise<void> => {\n const created = await args.context.http\n .request({ method: HttpMethod.Get, path: ownerPath, response: jsonValueSchema })\n .then(\n () => true,\n (cause: unknown) => !(isClientError(cause) && cause.status === 404),\n );\n if (!created) await sandbox.delete();\n };\n return {\n harness: { ...args.harness, environment: sandbox.id },\n ownerId,\n created: chosen ? { discard } : null,\n native,\n };\n};\n\nconst storeDocument = async (\n deps: AgentStartDepsIface,\n projectId: string,\n agent: ResolvedAgentIface,\n signal: AbortSignal | undefined,\n): Promise<void> => {\n if (agent.ref.document == null) return;\n await deps.context.http.request({\n method: HttpMethod.Put,\n path: `/v1/projects/${encodePath(projectId)}/agents/documents`,\n body: {\n schema: storeAgentDocumentRequestSchema,\n value: { document: agent.ref.document, hash: agent.hash },\n },\n response: storeAgentDocumentResponseSchema,\n signal,\n });\n};\n\nexport const checkHarness = (args: {\n context: ClientContextIface;\n projectId: string;\n hash: string;\n harness: NonNullable<ProvideDocumentIface['harness']>;\n compute?: ProvideDocumentIface['compute'];\n signal?: AbortSignal;\n}): Promise<HarnessCheckResponseIface> =>\n args.context.http.request({\n method: HttpMethod.Post,\n path: `/v1/projects/${encodePath(args.projectId)}/harnesses/check`,\n body: {\n schema: harnessCheckRequestSchema,\n value: {\n agent: args.hash,\n harness: args.harness,\n ...(args.compute == null ? {} : { compute: args.compute }),\n },\n },\n response: harnessCheckResponseSchema,\n signal: args.signal,\n });\n\nexport const startAgent = async (\n deps: AgentStartDepsIface,\n args: StartAgentArgsIface,\n): Promise<StartedAgentIface> => {\n // A closed client starts nothing, and closing it ends a host still opening.\n deps.context.closeSignal.throwIfAborted();\n const agent = await resolveAgentInput(args.agent, deps.codec);\n const own = provideDocumentOf(args.provide);\n const effective = layerProvide(own, args.shared ?? null);\n // An agent whose in-process code this process does not hold is refused\n // before anything is asked or created.\n const codeMissing = agent.inProcess.length > 0 && agent.code == null;\n if (effective.harness == null || args.projectId == null || codeMissing)\n return startResolved(deps, { args, agent, own, ownerId: args.owner.id });\n const placed = await withWorkersEnvironment({\n context: deps.context,\n projectId: args.projectId,\n harness: effective.harness,\n owner: args.owner,\n ownerIdReserved: args.ownerIdReserved,\n signal: args.signal,\n });\n if (placed.harness === effective.harness)\n return startResolved(deps, {\n args,\n agent,\n own,\n ownerId: args.owner.id,\n harnessNative: placed.native.length > 0,\n });\n const undo = (): void => {\n void placed.created?.discard().catch(() => undefined);\n };\n try {\n // Settings layered from the conversation become the participant's own,\n // now with the environment.\n const started = await startResolved(deps, {\n args,\n agent,\n own: { ...own, harness: placed.harness },\n ownerId: placed.ownerId,\n });\n return {\n ...started,\n abandon: () => {\n started.abandon();\n undo();\n },\n };\n } catch (cause) {\n undo();\n throw cause;\n }\n};\n\nconst startResolved = async (\n deps: AgentStartDepsIface,\n resolved: {\n args: StartAgentArgsIface;\n agent: ResolvedAgentIface;\n own: ProvideDocumentIface;\n ownerId: string | undefined;\n /** The harness uses files or shell natively and its settings name no environment. */\n harnessNative?: boolean;\n },\n): Promise<StartedAgentIface> => {\n const { args, agent, own, ownerId } = resolved;\n const closeSignal = deps.context.closeSignal;\n const signal = args.signal == null ? closeSignal : AbortSignal.any([args.signal, closeSignal]);\n const effective = layerProvide(own, args.shared ?? null);\n let ref = agent.ref;\n\n // Whether the harness serves files and shell on its own machine decides\n // what is still missing, and only the platform knows harnesses: ask it\n // whenever something is, whether or not this process may serve it.\n let unserved = capabilitiesToServeLocally({ agent, provide: effective, harness: null });\n // A native harness with no environment runs where `shell` is provided, which\n // this process may be even for an agent that requires neither files nor shell.\n const mayHostHarness =\n resolved.harnessNative === true &&\n deps.localCompute &&\n effective.harness?.environment == null &&\n !PROCESS_CAPABILITIES.some((capability) => effective.compute?.[capability] != null);\n let harness: HarnessCheckResponseIface | null = null;\n if (\n (unserved.length > 0 || mayHostHarness) &&\n effective.harness != null &&\n args.projectId != null\n ) {\n await storeDocument(deps, args.projectId, agent, args.signal);\n ref = { hash: agent.hash };\n harness = await checkHarness({\n context: deps.context,\n projectId: args.projectId,\n hash: agent.hash,\n harness: effective.harness,\n compute: effective.compute,\n signal: args.signal,\n });\n unserved = capabilitiesToServeLocally({ agent, provide: effective, harness });\n }\n const local = deps.localCompute ? unserved : [];\n\n const servesCode = agent.code != null && agent.inProcess.length > 0;\n const planned: ProvideDocumentIface = {\n ...effective,\n compute: {\n ...effective.compute,\n ...Object.fromEntries(local.map((capability) => [capability, LOCAL_PLACEHOLDER])),\n },\n };\n assertRequirementsMet({ agent, provide: planned, harness, servesCode });\n\n if (local.length === 0 && !servesCode)\n return {\n ref,\n provide: own,\n ownerId,\n host: null,\n abandon: () => undefined,\n established: () => undefined,\n };\n if (args.projectId == null)\n throw clientError({\n message:\n 'Serving compute or in-process code from this process needs a project: use client.project({ id })',\n status: 0,\n code: ClientErrorCode.InvalidRequest,\n });\n\n const host = await openLocalHost({\n dial: deps.dial,\n projectId: args.projectId,\n owner: { ...args.owner, id: ownerId },\n agent,\n capabilities: local,\n compute: deps.compute,\n signal,\n });\n if (closeSignal.aborted) {\n host.close();\n closeSignal.throwIfAborted();\n }\n deps.hosts.add(host);\n void host.closed.then(() => deps.hosts.delete(host));\n // The participant's compute wins whole over a conversation's, so with this\n // process's sandbox it also carries the compute it was layered from.\n const sandboxId = host.sandboxId;\n const provide =\n local.length === 0 || sandboxId == null\n ? own\n : {\n ...own,\n compute: {\n ...effective.compute,\n ...Object.fromEntries(local.map((capability) => [capability, sandboxId])),\n },\n };\n return {\n ref,\n provide,\n ownerId: host.ownerId,\n host,\n abandon: () => host.close(),\n established: () => host.established(),\n };\n};\n\n/**\n * Serves the agent's in-process code to an existing session or conversation\n * from this process, without compute: its provide is already what an earlier\n * call stored. Null when the agent has no in-process code.\n */\nexport const serveCodeFor = async (\n deps: AgentStartDepsIface,\n args: {\n projectId: string;\n agent: unknown;\n owner: { kind: LocalHostOwnerKind; id: string };\n signal?: AbortSignal;\n },\n): Promise<LocalHostIface | null> => {\n const closeSignal = deps.context.closeSignal;\n closeSignal.throwIfAborted();\n const agent = await resolveAgentInput(args.agent, deps.codec);\n if (agent.code == null || agent.inProcess.length === 0) return null;\n const host = await openLocalHost({\n dial: deps.dial,\n projectId: args.projectId,\n owner: args.owner,\n agent,\n capabilities: [],\n compute: deps.compute,\n signal: args.signal == null ? closeSignal : AbortSignal.any([args.signal, closeSignal]),\n });\n if (closeSignal.aborted) {\n host.close();\n closeSignal.throwIfAborted();\n }\n deps.hosts.add(host);\n void host.closed.then(() => deps.hosts.delete(host));\n host.established();\n return host;\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -25,6 +25,7 @@ export declare const createFakeTransport: () => {
|
|
|
25
25
|
subscriptions: string[];
|
|
26
26
|
listenerCount: (topic: string) => number;
|
|
27
27
|
};
|
|
28
|
+
export declare const withoutHarnessLookups: (requests: readonly RecordedRequestIface[]) => RecordedRequestIface[];
|
|
28
29
|
export declare const eventFrame: (args: {
|
|
29
30
|
topic: string;
|
|
30
31
|
kind: string;
|
|
@@ -45,6 +45,7 @@ const createFakeTransport = () => {
|
|
|
45
45
|
const listenerCount = (topic) => listeners.get(topic)?.size ?? 0;
|
|
46
46
|
return { transport, emit, subscriptions, listenerCount };
|
|
47
47
|
};
|
|
48
|
+
const withoutHarnessLookups = (requests) => requests.filter((request) => !request.path.endsWith("/harnesses/lookup"));
|
|
48
49
|
let cursor = 0;
|
|
49
50
|
const eventFrame = (args) => {
|
|
50
51
|
cursor += 1;
|
|
@@ -89,6 +90,7 @@ export {
|
|
|
89
90
|
eventFrame,
|
|
90
91
|
flush,
|
|
91
92
|
promptFrame,
|
|
92
|
-
sessionUpdateFrame
|
|
93
|
+
sessionUpdateFrame,
|
|
94
|
+
withoutHarnessLookups
|
|
93
95
|
};
|
|
94
96
|
//# sourceMappingURL=test-fakes.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/agent-client/test-fakes.ts"],
|
|
4
|
-
"sourcesContent": ["import type { JsonValue } from '@finalai/agent-protocol';\nimport * as z from 'zod';\nimport type { FetchIface } from \"./http.mjs\";\nimport type { RealtimeTransportFrameIface, RealtimeTransportIface } from \"./realtime.mjs\";\n\n// Dependency seams for SDK tests: a routed fake fetch and an in-memory\n// realtime transport. No module mocking.\n\nexport interface RecordedRequestIface {\n method: string;\n path: string;\n query: URLSearchParams;\n headers: Record<string, string>;\n credentials: RequestCredentials | undefined;\n body: JsonValue | null;\n}\n\nexport interface FakeResponseIface {\n status?: number;\n json?: JsonValue;\n text?: string;\n}\n\nexport type FakeRoute = (request: RecordedRequestIface) => FakeResponseIface;\n\nconst headerRecordSchema = z.record(z.string(), z.string());\n\nexport const createFakeFetch = (routes: Record<string, FakeRoute>) => {\n const requests: RecordedRequestIface[] = [];\n const fetch: FetchIface = async (input, init) => {\n const url = new URL(input);\n const bodyText = z.string().safeParse(init.body);\n const request: RecordedRequestIface = {\n method: init.method ?? 'GET',\n path: url.pathname,\n query: url.searchParams,\n headers: headerRecordSchema.safeParse(init.headers).data ?? {},\n credentials: init.credentials,\n body: bodyText.success ? z.json().parse(JSON.parse(bodyText.data)) : null,\n };\n requests.push(request);\n const route = routes[`${request.method} ${request.path}`];\n if (route == null) {\n return new Response(JSON.stringify({ error: { code: 'not_found', message: 'no route' } }), {\n status: 404,\n });\n }\n const response = route(request);\n const status = response.status ?? 200;\n const body = status === 204 ? null : (response.text ?? JSON.stringify(response.json ?? {}));\n return new Response(body, { status });\n };\n return { fetch, requests };\n};\n\nexport const createFakeTransport = () => {\n const listeners = new Map<string, Set<(frame: RealtimeTransportFrameIface) => void>>();\n const subscriptions: string[] = [];\n const transport: RealtimeTransportIface = {\n subscribe: (topic, onFrame) => {\n subscriptions.push(topic);\n const set = listeners.get(topic) ?? new Set();\n set.add(onFrame);\n listeners.set(topic, set);\n return () => set.delete(onFrame);\n },\n };\n const emit = (topic: string, frame: RealtimeTransportFrameIface): void => {\n for (const listener of [...(listeners.get(topic) ?? [])]) listener(frame);\n };\n const listenerCount = (topic: string): number => listeners.get(topic)?.size ?? 0;\n return { transport, emit, subscriptions, listenerCount };\n};\n\nlet cursor = 0;\n\nexport const eventFrame = (args: {\n topic: string;\n kind: string;\n payload: JsonValue;\n}): RealtimeTransportFrameIface => {\n cursor += 1;\n return {\n type: 'event',\n topic: args.topic,\n cursor: `${cursor}-0`,\n eventKey: `${args.kind}:${cursor}`,\n kind: args.kind,\n payload: args.payload,\n createdAt: '2026-10-09T14:02:12.004Z',\n };\n};\n\nexport const sessionUpdateFrame = (args: {\n seq: number;\n update: JsonValue;\n direction?: string;\n}): JsonValue => ({\n seq: args.seq,\n direction: args.direction ?? 'agent_to_client',\n at: '2026-10-09T14:02:12.004Z',\n frame: {\n jsonrpc: '2.0',\n method: 'session/update',\n params: { sessionId: 'ases_1', update: args.update },\n },\n});\n\nexport const promptFrame = (seq: number): JsonValue => ({\n seq,\n direction: 'client_to_agent',\n at: '2026-10-09T14:02:11.000Z',\n frame: {\n jsonrpc: '2.0',\n id: 1,\n method: 'session/prompt',\n params: { sessionId: 'ases_1', prompt: [] },\n },\n});\n\n/** Lets pending promise callbacks (replay fetches) run. */\nexport const flush = async (): Promise<void> => {\n for (let index = 0; index < 10; index += 1)\n await new Promise((resolve) => setTimeout(resolve, 0));\n};\n"],
|
|
5
|
-
"mappings": "AACA,YAAY,OAAO;AAwBnB,MAAM,qBAAqB,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC;AAEnD,MAAM,kBAAkB,CAAC,WAAsC;AACpE,QAAM,WAAmC,CAAC;AAC1C,QAAM,QAAoB,OAAO,OAAO,SAAS;AAC/C,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,UAAM,WAAW,EAAE,OAAO,EAAE,UAAU,KAAK,IAAI;AAC/C,UAAM,UAAgC;AAAA,MACpC,QAAQ,KAAK,UAAU;AAAA,MACvB,MAAM,IAAI;AAAA,MACV,OAAO,IAAI;AAAA,MACX,SAAS,mBAAmB,UAAU,KAAK,OAAO,EAAE,QAAQ,CAAC;AAAA,MAC7D,aAAa,KAAK;AAAA,MAClB,MAAM,SAAS,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,SAAS,IAAI,CAAC,IAAI;AAAA,IACvE;AACA,aAAS,KAAK,OAAO;AACrB,UAAM,QAAQ,OAAO,GAAG,QAAQ,MAAM,IAAI,QAAQ,IAAI,EAAE;AACxD,QAAI,SAAS,MAAM;AACjB,aAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,SAAS,WAAW,EAAE,CAAC,GAAG;AAAA,QACzF,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AACA,UAAM,WAAW,MAAM,OAAO;AAC9B,UAAM,SAAS,SAAS,UAAU;AAClC,UAAM,OAAO,WAAW,MAAM,OAAQ,SAAS,QAAQ,KAAK,UAAU,SAAS,QAAQ,CAAC,CAAC;AACzF,WAAO,IAAI,SAAS,MAAM,EAAE,OAAO,CAAC;AAAA,EACtC;AACA,SAAO,EAAE,OAAO,SAAS;AAC3B;AAEO,MAAM,sBAAsB,MAAM;AACvC,QAAM,YAAY,oBAAI,IAA+D;AACrF,QAAM,gBAA0B,CAAC;AACjC,QAAM,YAAoC;AAAA,IACxC,WAAW,CAAC,OAAO,YAAY;AAC7B,oBAAc,KAAK,KAAK;AACxB,YAAM,MAAM,UAAU,IAAI,KAAK,KAAK,oBAAI,IAAI;AAC5C,UAAI,IAAI,OAAO;AACf,gBAAU,IAAI,OAAO,GAAG;AACxB,aAAO,MAAM,IAAI,OAAO,OAAO;AAAA,IACjC;AAAA,EACF;AACA,QAAM,OAAO,CAAC,OAAe,UAA6C;AACxE,eAAW,YAAY,CAAC,GAAI,UAAU,IAAI,KAAK,KAAK,CAAC,CAAE,EAAG,UAAS,KAAK;AAAA,EAC1E;AACA,QAAM,gBAAgB,CAAC,UAA0B,UAAU,IAAI,KAAK,GAAG,QAAQ;AAC/E,SAAO,EAAE,WAAW,MAAM,eAAe,cAAc;AACzD;
|
|
4
|
+
"sourcesContent": ["import type { JsonValue } from '@finalai/agent-protocol';\nimport * as z from 'zod';\nimport type { FetchIface } from \"./http.mjs\";\nimport type { RealtimeTransportFrameIface, RealtimeTransportIface } from \"./realtime.mjs\";\n\n// Dependency seams for SDK tests: a routed fake fetch and an in-memory\n// realtime transport. No module mocking.\n\nexport interface RecordedRequestIface {\n method: string;\n path: string;\n query: URLSearchParams;\n headers: Record<string, string>;\n credentials: RequestCredentials | undefined;\n body: JsonValue | null;\n}\n\nexport interface FakeResponseIface {\n status?: number;\n json?: JsonValue;\n text?: string;\n}\n\nexport type FakeRoute = (request: RecordedRequestIface) => FakeResponseIface;\n\nconst headerRecordSchema = z.record(z.string(), z.string());\n\nexport const createFakeFetch = (routes: Record<string, FakeRoute>) => {\n const requests: RecordedRequestIface[] = [];\n const fetch: FetchIface = async (input, init) => {\n const url = new URL(input);\n const bodyText = z.string().safeParse(init.body);\n const request: RecordedRequestIface = {\n method: init.method ?? 'GET',\n path: url.pathname,\n query: url.searchParams,\n headers: headerRecordSchema.safeParse(init.headers).data ?? {},\n credentials: init.credentials,\n body: bodyText.success ? z.json().parse(JSON.parse(bodyText.data)) : null,\n };\n requests.push(request);\n const route = routes[`${request.method} ${request.path}`];\n if (route == null) {\n return new Response(JSON.stringify({ error: { code: 'not_found', message: 'no route' } }), {\n status: 404,\n });\n }\n const response = route(request);\n const status = response.status ?? 200;\n const body = status === 204 ? null : (response.text ?? JSON.stringify(response.json ?? {}));\n return new Response(body, { status });\n };\n return { fetch, requests };\n};\n\nexport const createFakeTransport = () => {\n const listeners = new Map<string, Set<(frame: RealtimeTransportFrameIface) => void>>();\n const subscriptions: string[] = [];\n const transport: RealtimeTransportIface = {\n subscribe: (topic, onFrame) => {\n subscriptions.push(topic);\n const set = listeners.get(topic) ?? new Set();\n set.add(onFrame);\n listeners.set(topic, set);\n return () => set.delete(onFrame);\n },\n };\n const emit = (topic: string, frame: RealtimeTransportFrameIface): void => {\n for (const listener of [...(listeners.get(topic) ?? [])]) listener(frame);\n };\n const listenerCount = (topic: string): number => listeners.get(topic)?.size ?? 0;\n return { transport, emit, subscriptions, listenerCount };\n};\n\n// The requests a test asserts on, without the harness lookups the SDK makes to\n// learn whether settings that name no environment need a Workers sandbox.\nexport const withoutHarnessLookups = (\n requests: readonly RecordedRequestIface[],\n): RecordedRequestIface[] =>\n requests.filter((request) => !request.path.endsWith('/harnesses/lookup'));\n\nlet cursor = 0;\n\nexport const eventFrame = (args: {\n topic: string;\n kind: string;\n payload: JsonValue;\n}): RealtimeTransportFrameIface => {\n cursor += 1;\n return {\n type: 'event',\n topic: args.topic,\n cursor: `${cursor}-0`,\n eventKey: `${args.kind}:${cursor}`,\n kind: args.kind,\n payload: args.payload,\n createdAt: '2026-10-09T14:02:12.004Z',\n };\n};\n\nexport const sessionUpdateFrame = (args: {\n seq: number;\n update: JsonValue;\n direction?: string;\n}): JsonValue => ({\n seq: args.seq,\n direction: args.direction ?? 'agent_to_client',\n at: '2026-10-09T14:02:12.004Z',\n frame: {\n jsonrpc: '2.0',\n method: 'session/update',\n params: { sessionId: 'ases_1', update: args.update },\n },\n});\n\nexport const promptFrame = (seq: number): JsonValue => ({\n seq,\n direction: 'client_to_agent',\n at: '2026-10-09T14:02:11.000Z',\n frame: {\n jsonrpc: '2.0',\n id: 1,\n method: 'session/prompt',\n params: { sessionId: 'ases_1', prompt: [] },\n },\n});\n\n/** Lets pending promise callbacks (replay fetches) run. */\nexport const flush = async (): Promise<void> => {\n for (let index = 0; index < 10; index += 1)\n await new Promise((resolve) => setTimeout(resolve, 0));\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AgentIface } from '@finalai/agent-definition';
|
|
2
|
+
import type { AgentDocumentIface } from '@finalai/agent-provider/document';
|
|
3
|
+
import { type AcpAdapterDefinitionIface, type HarnessDefinitionIface } from '@finalai/agent-provider/harness-definition';
|
|
4
|
+
import * as z from 'zod';
|
|
5
|
+
declare const moduleNamespaceSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
6
|
+
export type ModuleNamespace = z.output<typeof moduleNamespaceSchema>;
|
|
7
|
+
export type ImportModule = (url: string) => Promise<ModuleNamespace>;
|
|
8
|
+
export declare const importModule: ImportModule;
|
|
9
|
+
export declare enum DefinitionKind {
|
|
10
|
+
Agent = "agent",
|
|
11
|
+
Harness = "harness",
|
|
12
|
+
AcpAdapter = "acp-adapter"
|
|
13
|
+
}
|
|
14
|
+
export type LoadedDefinitionIface = {
|
|
15
|
+
kind: DefinitionKind.Agent;
|
|
16
|
+
agent: AgentIface;
|
|
17
|
+
document: AgentDocumentIface;
|
|
18
|
+
} | {
|
|
19
|
+
kind: DefinitionKind.Harness;
|
|
20
|
+
document: HarnessDefinitionIface;
|
|
21
|
+
} | {
|
|
22
|
+
kind: DefinitionKind.AcpAdapter;
|
|
23
|
+
document: AcpAdapterDefinitionIface;
|
|
24
|
+
};
|
|
25
|
+
export type LoadedModuleResult = ({
|
|
26
|
+
ok: true;
|
|
27
|
+
exportName: string;
|
|
28
|
+
} & LoadedDefinitionIface) | {
|
|
29
|
+
ok: false;
|
|
30
|
+
message: string;
|
|
31
|
+
};
|
|
32
|
+
export declare const loadDefinitionModule: (args: {
|
|
33
|
+
module: string;
|
|
34
|
+
exportName: string | null;
|
|
35
|
+
cwd: string;
|
|
36
|
+
importModule?: ImportModule;
|
|
37
|
+
documentOf: (agent: AgentIface) => AgentDocumentIface;
|
|
38
|
+
}) => Promise<LoadedModuleResult>;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import {
|
|
4
|
+
acpAdapterDefinitionSchema,
|
|
5
|
+
harnessDefinitionSchema
|
|
6
|
+
} from "@finalai/agent-provider/harness-definition";
|
|
7
|
+
import * as z from "zod";
|
|
8
|
+
const moduleNamespaceSchema = z.record(z.string(), z.unknown());
|
|
9
|
+
const importModule = async (url) => moduleNamespaceSchema.parse(await import(
|
|
10
|
+
/* @vite-ignore */
|
|
11
|
+
url
|
|
12
|
+
));
|
|
13
|
+
const agentSchema = z.custom(
|
|
14
|
+
(value) => typeof value === "object" && value != null && "require" in value && "name" in value
|
|
15
|
+
);
|
|
16
|
+
var DefinitionKind = /* @__PURE__ */ ((DefinitionKind2) => {
|
|
17
|
+
DefinitionKind2["Agent"] = "agent";
|
|
18
|
+
DefinitionKind2["Harness"] = "harness";
|
|
19
|
+
DefinitionKind2["AcpAdapter"] = "acp-adapter";
|
|
20
|
+
return DefinitionKind2;
|
|
21
|
+
})(DefinitionKind || {});
|
|
22
|
+
const kindOf = (value) => {
|
|
23
|
+
if (agentSchema.safeParse(value).success) return "agent" /* Agent */;
|
|
24
|
+
if (harnessDefinitionSchema.safeParse(value).success) return "harness" /* Harness */;
|
|
25
|
+
if (acpAdapterDefinitionSchema.safeParse(value).success) return "acp-adapter" /* AcpAdapter */;
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
const loadDefinitionModule = async (args) => {
|
|
29
|
+
let loaded;
|
|
30
|
+
try {
|
|
31
|
+
loaded = await (args.importModule ?? importModule)(
|
|
32
|
+
pathToFileURL(resolve(args.cwd, args.module)).href
|
|
33
|
+
);
|
|
34
|
+
} catch (cause) {
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
message: `cannot load ${args.module}: ${cause instanceof Error ? cause.message : String(cause)}`
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const definitions = Object.entries(loaded).filter(([, value2]) => kindOf(value2) != null);
|
|
41
|
+
const pick = () => {
|
|
42
|
+
if (args.exportName != null)
|
|
43
|
+
return args.exportName in loaded ? [args.exportName, loaded[args.exportName]] : `${args.module} has no export ${args.exportName}`;
|
|
44
|
+
for (const name of ["agent", "default"])
|
|
45
|
+
if (definitions.some(([candidate]) => candidate === name)) return [name, loaded[name]];
|
|
46
|
+
const [only, ...others] = definitions;
|
|
47
|
+
if (only == null)
|
|
48
|
+
return `${args.module} exports no agent, harness or ACP adapter; define one with defineAgent, defineHarness or defineAcpAdapter`;
|
|
49
|
+
if (others.length > 0)
|
|
50
|
+
return `${args.module} exports several definitions (${definitions.map(([name]) => name).join(", ")}); choose one with --export`;
|
|
51
|
+
return only;
|
|
52
|
+
};
|
|
53
|
+
const picked = pick();
|
|
54
|
+
if (typeof picked === "string") return { ok: false, message: picked };
|
|
55
|
+
const [exportName, value] = picked;
|
|
56
|
+
const failed = (cause) => ({
|
|
57
|
+
ok: false,
|
|
58
|
+
message: `${args.module}#${exportName}: ${cause instanceof Error ? cause.message : String(cause)}`
|
|
59
|
+
});
|
|
60
|
+
const harness = harnessDefinitionSchema.safeParse(value);
|
|
61
|
+
if (harness.success)
|
|
62
|
+
return { ok: true, exportName, kind: "harness" /* Harness */, document: harness.data };
|
|
63
|
+
const adapter = acpAdapterDefinitionSchema.safeParse(value);
|
|
64
|
+
if (adapter.success)
|
|
65
|
+
return { ok: true, exportName, kind: "acp-adapter" /* AcpAdapter */, document: adapter.data };
|
|
66
|
+
const agent = agentSchema.safeParse(value);
|
|
67
|
+
if (!agent.success)
|
|
68
|
+
return {
|
|
69
|
+
ok: false,
|
|
70
|
+
message: `${args.module}#${exportName} is not an agent, a harness or an ACP adapter`
|
|
71
|
+
};
|
|
72
|
+
try {
|
|
73
|
+
return {
|
|
74
|
+
ok: true,
|
|
75
|
+
exportName,
|
|
76
|
+
kind: "agent" /* Agent */,
|
|
77
|
+
agent: agent.data,
|
|
78
|
+
document: args.documentOf(agent.data)
|
|
79
|
+
};
|
|
80
|
+
} catch (cause) {
|
|
81
|
+
return failed(cause);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
export {
|
|
85
|
+
DefinitionKind,
|
|
86
|
+
importModule,
|
|
87
|
+
loadDefinitionModule
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=agent-module.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/cli/agent-module.ts"],
|
|
4
|
+
"sourcesContent": ["import { resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { AgentIface } from '@finalai/agent-definition';\nimport type { AgentDocumentIface } from '@finalai/agent-provider/document';\nimport {\n acpAdapterDefinitionSchema,\n harnessDefinitionSchema,\n type AcpAdapterDefinitionIface,\n type HarnessDefinitionIface,\n} from '@finalai/agent-provider/harness-definition';\nimport * as z from 'zod';\n\nconst moduleNamespaceSchema = z.record(z.string(), z.unknown());\n\nexport type ModuleNamespace = z.output<typeof moduleNamespaceSchema>;\n\nexport type ImportModule = (url: string) => Promise<ModuleNamespace>;\n\nexport const importModule: ImportModule = async (url) =>\n moduleNamespaceSchema.parse(await import(/* @vite-ignore */ url));\n\nconst agentSchema = z.custom<AgentIface>(\n (value) => typeof value === 'object' && value != null && 'require' in value && 'name' in value,\n);\n\n// What a module can export for `print` and `publish`.\nexport enum DefinitionKind {\n Agent = 'agent',\n Harness = 'harness',\n AcpAdapter = 'acp-adapter',\n}\n\nconst kindOf = (value: unknown): DefinitionKind | null => {\n if (agentSchema.safeParse(value).success) return DefinitionKind.Agent;\n if (harnessDefinitionSchema.safeParse(value).success) return DefinitionKind.Harness;\n if (acpAdapterDefinitionSchema.safeParse(value).success) return DefinitionKind.AcpAdapter;\n return null;\n};\n\nexport type LoadedDefinitionIface =\n | { kind: DefinitionKind.Agent; agent: AgentIface; document: AgentDocumentIface }\n | { kind: DefinitionKind.Harness; document: HarnessDefinitionIface }\n | { kind: DefinitionKind.AcpAdapter; document: AcpAdapterDefinitionIface };\n\nexport type LoadedModuleResult =\n | ({ ok: true; exportName: string } & LoadedDefinitionIface)\n | { ok: false; message: string };\n\n// Loads a module and finds the definition it exports (an agent, a harness or\n// an ACP adapter): `--export <name>` when given, else `agent`, else\n// `default`, else its only export that is a definition.\nexport const loadDefinitionModule = async (args: {\n module: string;\n exportName: string | null;\n cwd: string;\n importModule?: ImportModule;\n documentOf: (agent: AgentIface) => AgentDocumentIface;\n}): Promise<LoadedModuleResult> => {\n let loaded: ModuleNamespace;\n try {\n loaded = await (args.importModule ?? importModule)(\n pathToFileURL(resolve(args.cwd, args.module)).href,\n );\n } catch (cause) {\n return {\n ok: false,\n message: `cannot load ${args.module}: ${cause instanceof Error ? cause.message : String(cause)}`,\n };\n }\n const definitions = Object.entries(loaded).filter(([, value]) => kindOf(value) != null);\n const pick = (): [string, unknown] | string => {\n if (args.exportName != null)\n return args.exportName in loaded\n ? [args.exportName, loaded[args.exportName]]\n : `${args.module} has no export ${args.exportName}`;\n for (const name of ['agent', 'default'])\n if (definitions.some(([candidate]) => candidate === name)) return [name, loaded[name]];\n const [only, ...others] = definitions;\n if (only == null)\n return `${args.module} exports no agent, harness or ACP adapter; define one with defineAgent, defineHarness or defineAcpAdapter`;\n if (others.length > 0)\n return `${args.module} exports several definitions (${definitions.map(([name]) => name).join(', ')}); choose one with --export`;\n return only;\n };\n const picked = pick();\n if (typeof picked === 'string') return { ok: false, message: picked };\n const [exportName, value] = picked;\n const failed = (cause: unknown): LoadedModuleResult => ({\n ok: false,\n message: `${args.module}#${exportName}: ${cause instanceof Error ? cause.message : String(cause)}`,\n });\n const harness = harnessDefinitionSchema.safeParse(value);\n if (harness.success)\n return { ok: true, exportName, kind: DefinitionKind.Harness, document: harness.data };\n const adapter = acpAdapterDefinitionSchema.safeParse(value);\n if (adapter.success)\n return { ok: true, exportName, kind: DefinitionKind.AcpAdapter, document: adapter.data };\n const agent = agentSchema.safeParse(value);\n if (!agent.success)\n return {\n ok: false,\n message: `${args.module}#${exportName} is not an agent, a harness or an ACP adapter`,\n };\n try {\n return {\n ok: true,\n exportName,\n kind: DefinitionKind.Agent,\n agent: agent.data,\n document: args.documentOf(agent.data),\n };\n } catch (cause) {\n return failed(cause);\n }\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["DefinitionKind", "value"]
|
|
7
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
import { type AgentIface } from '@finalai/agent-definition';
|
|
2
|
+
import type { AgentDocumentIface } from '@finalai/agent-provider/document';
|
|
1
3
|
import type { FetchIface } from "../agent-client/http.mjs";
|
|
2
|
-
import { type ImportModule } from "./
|
|
3
|
-
import { type
|
|
4
|
-
import type { OutputIface } from "./output.mjs";
|
|
5
|
-
export declare const DEFAULT_AGENTS_HOST = "https://agent-session.final.ai/api";
|
|
4
|
+
import { type ImportModule } from "./agent-module.mjs";
|
|
5
|
+
import { type OutputIface } from "./output.mjs";
|
|
6
6
|
export interface AgentsCliDepsIface {
|
|
7
7
|
argv: string[];
|
|
8
8
|
env: Record<string, string | undefined>;
|
|
9
9
|
cwd: string;
|
|
10
10
|
output: OutputIface;
|
|
11
11
|
fetch?: FetchIface;
|
|
12
|
-
listFiles?: ListFiles;
|
|
13
|
-
signal?: AbortSignal;
|
|
14
12
|
importModule?: ImportModule;
|
|
13
|
+
documentOf?: (agent: AgentIface) => AgentDocumentIface;
|
|
14
|
+
signal?: AbortSignal;
|
|
15
15
|
}
|
|
16
16
|
export declare const runAgentsCommand: (deps: AgentsCliDepsIface) => Promise<number>;
|