@artinet/fleet 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +257 -0
  2. package/dist/src/default.d.ts +696 -0
  3. package/dist/src/default.js +17 -0
  4. package/dist/src/index.d.ts +6 -0
  5. package/dist/src/index.js +6 -0
  6. package/dist/src/routes/create/index.d.ts +1317 -0
  7. package/dist/src/routes/create/index.js +3 -0
  8. package/dist/src/routes/index.d.ts +2 -0
  9. package/dist/src/routes/index.js +2 -0
  10. package/dist/src/routes/request/implementation/index.d.ts +4 -0
  11. package/dist/src/routes/request/implementation/index.js +4 -0
  12. package/dist/src/routes/request/implementation/invoke.d.ts +8 -0
  13. package/dist/src/routes/request/implementation/invoke.js +150 -0
  14. package/dist/src/routes/request/implementation/load.d.ts +2 -0
  15. package/dist/src/routes/request/implementation/load.js +50 -0
  16. package/dist/src/routes/request/implementation/request.d.ts +2 -0
  17. package/dist/src/routes/request/implementation/request.js +28 -0
  18. package/dist/src/routes/request/implementation/test-invoke.d.ts +3 -0
  19. package/dist/src/routes/request/implementation/test-invoke.js +42 -0
  20. package/dist/src/routes/request/index.d.ts +4 -0
  21. package/dist/src/routes/request/index.js +4 -0
  22. package/dist/src/routes/request/interceptors/fetch-agent.d.ts +2 -0
  23. package/dist/src/routes/request/interceptors/fetch-agent.js +26 -0
  24. package/dist/src/routes/request/interceptors/get-agents.d.ts +2 -0
  25. package/dist/src/routes/request/interceptors/get-agents.js +38 -0
  26. package/dist/src/routes/request/interceptors/index.d.ts +2 -0
  27. package/dist/src/routes/request/interceptors/index.js +2 -0
  28. package/dist/src/routes/request/request.d.ts +8 -0
  29. package/dist/src/routes/request/request.js +16 -0
  30. package/dist/src/routes/request/types/definitions.d.ts +733 -0
  31. package/dist/src/routes/request/types/definitions.js +11 -0
  32. package/dist/src/routes/request/types/index.d.ts +1 -0
  33. package/dist/src/routes/request/types/index.js +1 -0
  34. package/dist/src/server/express/agent-request.d.ts +26 -0
  35. package/dist/src/server/express/agent-request.js +44 -0
  36. package/dist/src/server/express/deploy-request.d.ts +14 -0
  37. package/dist/src/server/express/deploy-request.js +19 -0
  38. package/dist/src/server/express/fleet.d.ts +3 -0
  39. package/dist/src/server/express/fleet.js +2 -0
  40. package/dist/src/server/express/index.d.ts +4 -0
  41. package/dist/src/server/express/index.js +4 -0
  42. package/dist/src/server/express/rpc.d.ts +12 -0
  43. package/dist/src/server/express/rpc.js +38 -0
  44. package/dist/src/server/express/server.d.ts +26 -0
  45. package/dist/src/server/express/server.js +115 -0
  46. package/dist/src/server/express/test-request.d.ts +14 -0
  47. package/dist/src/server/express/test-request.js +47 -0
  48. package/dist/src/server/express/utils.d.ts +5 -0
  49. package/dist/src/server/express/utils.js +11 -0
  50. package/dist/src/server/index.d.ts +1 -0
  51. package/dist/src/server/index.js +1 -0
  52. package/dist/src/settings.d.ts +14 -0
  53. package/dist/src/settings.js +1 -0
  54. package/dist/src/ship.d.ts +2 -0
  55. package/dist/src/ship.js +15 -0
  56. package/dist/src/storage.d.ts +5 -0
  57. package/dist/src/storage.js +8 -0
  58. package/dist/src/types.d.ts +14 -0
  59. package/dist/src/types.js +1 -0
  60. package/package.json +90 -0
@@ -0,0 +1,3 @@
1
+ import * as armada from "@artinet/armada";
2
+ export const CreateAgent = armada.CreateAgent;
3
+ export const CreateAgentRequestSchema = armada.CreateAgentRequestSchema;
@@ -0,0 +1,2 @@
1
+ export * from "./create/index.js";
2
+ export * from "./request/index.js";
@@ -0,0 +1,2 @@
1
+ export * from "./create/index.js";
2
+ export * from "./request/index.js";
@@ -0,0 +1,4 @@
1
+ export * from "./request.js";
2
+ export * from "./invoke.js";
3
+ export * from "./load.js";
4
+ export * from "./test-invoke.js";
@@ -0,0 +1,4 @@
1
+ export * from "./request.js";
2
+ export * from "./invoke.js";
3
+ export * from "./load.js";
4
+ export * from "./test-invoke.js";
@@ -0,0 +1,8 @@
1
+ import { z } from "zod/v4";
2
+ import * as sdk from "@artinet/sdk";
3
+ import { RequestAgentRoute, invokeFunction } from "../types/definitions.js";
4
+ export declare const invoke: (type: "success" | "error" | "stream", request: RequestAgentRoute["request"], invocable: Promise<sdk.A2A.ResponseResult | sdk.A2A.AgentCard> | AsyncIterable<sdk.A2A.Update>) => Promise<RequestAgentRoute["response"] | null>;
5
+ export declare const callAgent: (request: RequestAgentRoute["request"], agent: sdk.A2A.Service, params?: NonNullable<z.output<typeof sdk.A2A.RequestParamSchema>> | {
6
+ validation: string;
7
+ }) => Promise<RequestAgentRoute["response"] | null>;
8
+ export declare const invokeAgent: invokeFunction;
@@ -0,0 +1,150 @@
1
+ import * as sdk from "@artinet/sdk";
2
+ import { assert } from "console";
3
+ function isClient(agent) {
4
+ return agent instanceof sdk.A2AClient;
5
+ }
6
+ export const invoke = async (type, request, invocable) => {
7
+ let result = undefined;
8
+ try {
9
+ sdk.logger.info(`invoke:${request.method}`);
10
+ sdk.logger.debug(`invoke:${request.method}`, { params: request.params });
11
+ result = await invocable;
12
+ sdk.logger.debug(`invocation completed:${request.method}`, { result });
13
+ }
14
+ catch (error) {
15
+ sdk.logger.error(`invocation error:${request.method}:error:${JSON.stringify(error, null, 2)}`, { error });
16
+ return {
17
+ type: "error",
18
+ error: error,
19
+ };
20
+ }
21
+ if (!result) {
22
+ sdk.logger.error(`invocation failed:${request.method}`, { result });
23
+ return {
24
+ type: "error",
25
+ error: sdk.INTERNAL_ERROR({
26
+ message: "Internal error: No result from invocation",
27
+ method: request.method,
28
+ }),
29
+ };
30
+ }
31
+ if (type === "success") {
32
+ return {
33
+ type: "success",
34
+ result: result,
35
+ };
36
+ }
37
+ if (type === "stream") {
38
+ return {
39
+ type: "stream",
40
+ stream: result,
41
+ };
42
+ }
43
+ return {
44
+ type: "error",
45
+ error: sdk.INTERNAL_ERROR({
46
+ message: "Internal error: Invalid result type",
47
+ method: request.method,
48
+ }),
49
+ };
50
+ };
51
+ export const callAgent = async (request, agent, params = { validation: "no params provided" }) => {
52
+ switch (request.method) {
53
+ case "message/send": {
54
+ return await invoke("success", request, agent.sendMessage(params));
55
+ }
56
+ case "message/stream": {
57
+ return await invoke("stream", request, agent.streamMessage(params));
58
+ }
59
+ case "task/resubscribe": {
60
+ return await invoke("stream", request, agent.resubscribe(params));
61
+ }
62
+ case "task/get": {
63
+ return await invoke("success", request, agent.getTask(params));
64
+ }
65
+ case "task/cancel": {
66
+ return await invoke("success", request, agent.cancelTask(params));
67
+ }
68
+ case "task/pushNotificationConfig/set": {
69
+ if (!isClient(agent)) {
70
+ throw sdk.PUSH_NOTIFICATION_NOT_SUPPORTED({
71
+ data: {
72
+ message: "Push notifications are not supported for clients",
73
+ method: request.method,
74
+ },
75
+ });
76
+ }
77
+ return await invoke("success", request, agent.setTaskPushNotification(params));
78
+ }
79
+ case "task/pushNotificationConfig/get": {
80
+ if (!isClient(agent)) {
81
+ throw sdk.PUSH_NOTIFICATION_NOT_SUPPORTED({
82
+ data: {
83
+ message: "Push notifications are not supported for clients",
84
+ method: request.method,
85
+ },
86
+ });
87
+ }
88
+ return await invoke("success", request, agent.getTaskPushNotification(params));
89
+ }
90
+ case "task/pushNotificationConfig/list": {
91
+ throw sdk.PUSH_NOTIFICATION_NOT_SUPPORTED({
92
+ data: {
93
+ message: "Push notifications are not supported for clients",
94
+ method: request.method,
95
+ },
96
+ });
97
+ }
98
+ case "task/pushNotificationConfig/delete": {
99
+ throw sdk.PUSH_NOTIFICATION_NOT_SUPPORTED({
100
+ data: {
101
+ message: "Push notifications are not supported for clients",
102
+ method: request.method,
103
+ },
104
+ });
105
+ }
106
+ case "agentcard/get":
107
+ case "agent/getAuthenticatedExtendedCard": {
108
+ return await invoke("success", request, agent.getAgentCard());
109
+ }
110
+ default:
111
+ throw sdk.METHOD_NOT_FOUND({
112
+ data: {
113
+ message: "Method not found",
114
+ method: request.method,
115
+ },
116
+ });
117
+ }
118
+ };
119
+ export const invokeAgent = async (request, _agent) => {
120
+ sdk.logger.info("Invoking agent: " + request.method);
121
+ const _params = await sdk.validateSchema(sdk.A2A.RequestParamSchema, request.params);
122
+ const params = _params ?? { validation: "no params provided" };
123
+ sdk.logger.debug(`invokeAgent[${request.method}]: incoming params: ${sdk.formatJson(params)}`);
124
+ /* Support for A2AClient requests TBD */
125
+ assert(!isClient(_agent), "A2AClient requests are not supported");
126
+ //TODO: This proxy pattern is temporary until we align the A2AClient with the latest protocol changes
127
+ let agent = _agent;
128
+ if (isClient(_agent)) {
129
+ sdk.logger.debug(`invokeAgent[${request.method}]: creating proxy client`);
130
+ agent = {
131
+ ..._agent,
132
+ streamMessage: async function* (params) {
133
+ yield* _agent.sendStreamingMessage(params);
134
+ },
135
+ resubscribe: async function* (params) {
136
+ yield* _agent.resubscribeTask(params);
137
+ },
138
+ };
139
+ }
140
+ const response = await callAgent(request, agent, params);
141
+ if (!response) {
142
+ throw sdk.INTERNAL_ERROR({
143
+ data: {
144
+ message: "Internal error: No response from agent",
145
+ method: request.method,
146
+ },
147
+ });
148
+ }
149
+ return response;
150
+ };
@@ -0,0 +1,2 @@
1
+ import { loadFunction } from "../types/definitions.js";
2
+ export declare const loadAgent: loadFunction;
@@ -0,0 +1,50 @@
1
+ import { orc8 } from "orc8";
2
+ import { openaiProvider } from "orc8/openai";
3
+ import * as sdk from "@artinet/sdk";
4
+ import { Runtime } from "@artinet/types";
5
+ const DEFAULT_INSTRUCTIONS = "You are a helpful assistant that can use tools and agents to fulfill requests.";
6
+ const requiredAgentsNotLoaded = (config, context) => {
7
+ return ((!context.agents || !context.agents.length) &&
8
+ config.agentIds &&
9
+ config.agentIds.length > 0);
10
+ };
11
+ const missingAgents = (config, context) => {
12
+ return (config.agentIds?.filter((id) => !context.agents?.[id]).join(", ") ?? null);
13
+ };
14
+ export const loadAgent = async (config, context, provider = process.env.OPENAI_API_KEY
15
+ ? openaiProvider({
16
+ apiKey: process.env.OPENAI_API_KEY,
17
+ baseURL: context?.inferenceProviderUrl,
18
+ })
19
+ : undefined) => {
20
+ if (!context) {
21
+ throw sdk.INTERNAL_ERROR({
22
+ message: "Context not found",
23
+ });
24
+ }
25
+ const o8 = orc8.create({
26
+ ...config,
27
+ modelId: config.modelId ?? "gpt-4o",
28
+ instructions: config.instructions ??
29
+ context.defaultInstructions ??
30
+ DEFAULT_INSTRUCTIONS,
31
+ provider,
32
+ });
33
+ if (requiredAgentsNotLoaded(config, context)) {
34
+ throw sdk.INTERNAL_ERROR({
35
+ message: `Agents not found: ${missingAgents(config, context)}`,
36
+ });
37
+ }
38
+ if (missingAgents(config, context)) {
39
+ sdk.logger.warn(`Missing agents: ${missingAgents(config, context)}`);
40
+ }
41
+ Object.values(context.agents ?? {}).forEach((agent) => o8.add(agent));
42
+ config.services
43
+ .filter(Runtime.isToolInstance)
44
+ .filter((service) => Runtime.MCPStdioArgumentsSchema.safeParse(service.arguments).success)
45
+ .map((service) => service.arguments)
46
+ .forEach((args) => {
47
+ o8.add(args);
48
+ });
49
+ return o8.agent;
50
+ };
@@ -0,0 +1,2 @@
1
+ import { RequestAgentRoute } from "../types/definitions.js";
2
+ export declare const requestImplementation: RequestAgentRoute["implementation"];
@@ -0,0 +1,28 @@
1
+ import { AgentConfigurationSchema } from "agent-def";
2
+ import * as sdk from "@artinet/sdk";
3
+ export const requestImplementation = async (request, context) => {
4
+ if (!context.target) {
5
+ throw sdk.INTERNAL_ERROR({
6
+ message: `Agent ${context.agentId} not found: ${sdk.formatJson(context.found?.error ?? { error: "Unknown error" })}`,
7
+ method: request.method,
8
+ });
9
+ }
10
+ const agentConfig = await sdk.validateSchema(AgentConfigurationSchema, context.target);
11
+ const agent = await context.load(agentConfig, context);
12
+ if (!agent) {
13
+ throw sdk.INTERNAL_ERROR({
14
+ data: {
15
+ message: `Agent ${context.agentId} failed to load`,
16
+ },
17
+ });
18
+ }
19
+ const response = await context.invoke(request, agent, context);
20
+ if (!response) {
21
+ throw sdk.INTERNAL_ERROR({
22
+ data: {
23
+ message: `Agent ${context.agentId} failed to invoke`,
24
+ },
25
+ });
26
+ }
27
+ return response;
28
+ };
@@ -0,0 +1,3 @@
1
+ import { TestAgentRoute } from "../types/definitions.js";
2
+ import { Agent } from "../types/definitions.js";
3
+ export declare const testInvoke: (request: TestAgentRoute["request"], _agent: Agent) => Promise<TestAgentRoute["response"] | null>;
@@ -0,0 +1,42 @@
1
+ import * as sdk from "@artinet/sdk";
2
+ import { TestRequestSchema } from "../types/definitions.js";
3
+ import { v4 as uuidv4 } from "uuid";
4
+ const getId = (request) => {
5
+ let id = request.id ?? request.agentId;
6
+ if (!id) {
7
+ sdk.logger.debug("No id provided, generating a new one");
8
+ id = uuidv4();
9
+ }
10
+ return id;
11
+ };
12
+ export const testInvoke = async (request, _agent) => {
13
+ if (_agent instanceof sdk.A2AClient) {
14
+ throw sdk.INVALID_REQUEST({
15
+ message: "Test agent requests are not supported for A2AClients",
16
+ id: request.id,
17
+ agentId: request.agentId,
18
+ });
19
+ }
20
+ const id = getId(request);
21
+ sdk.logger.info("Invoking test agent: ", { id });
22
+ const testRequest = await sdk.validateSchema(TestRequestSchema, request.params);
23
+ if (!testRequest || !testRequest.tests || testRequest.tests.length === 0) {
24
+ throw sdk.INVALID_PARAMS({
25
+ message: "Invalid parameters for testing: no tests provided",
26
+ id,
27
+ agentId: request.agentId,
28
+ tests: testRequest.tests,
29
+ });
30
+ }
31
+ sdk.logger.debug(`invokeTestAgent[${id}]: incoming tests: ${sdk.formatJson(testRequest.tests)}`);
32
+ const asyncIterable = async function* () {
33
+ for (const test of testRequest.tests) {
34
+ sdk.logger.info(`testInvoke[${id}]: starting test: ${test.message.messageId}`);
35
+ yield* await _agent.streamMessage(test);
36
+ }
37
+ };
38
+ return {
39
+ type: "stream",
40
+ stream: asyncIterable(),
41
+ };
42
+ };
@@ -0,0 +1,4 @@
1
+ export * from "./implementation/index.js";
2
+ export * from "./interceptors/index.js";
3
+ export * from "./types/index.js";
4
+ export * from "./request.js";
@@ -0,0 +1,4 @@
1
+ export * from "./implementation/index.js";
2
+ export * from "./interceptors/index.js";
3
+ export * from "./types/index.js";
4
+ export * from "./request.js";
@@ -0,0 +1,2 @@
1
+ import { RequestAgentRoute } from "../types/definitions.js";
2
+ export declare const FetchAgent: RequestAgentRoute["intercept"];
@@ -0,0 +1,26 @@
1
+ import * as armada from "@artinet/armada";
2
+ import { AgentConfigurationSchema } from "agent-def";
3
+ import * as sdk from "@artinet/sdk";
4
+ export const FetchAgent = {
5
+ trigger: ({ context }) => !context.target,
6
+ action: async ({ request, context, }) => armada
7
+ .TryFindBase({ request, context }, {
8
+ uri: context.agentId,
9
+ throwNotFound: true,
10
+ storage: context.storage,
11
+ find: armada.FindAgent,
12
+ })
13
+ .then(async (request) => {
14
+ if (!context.found) {
15
+ throw sdk.INTERNAL_ERROR({
16
+ data: {
17
+ message: `agent ${context.agentId} not found`,
18
+ },
19
+ });
20
+ }
21
+ context.target = await sdk.validateSchema(AgentConfigurationSchema, Object.values(context.found.results)[0]);
22
+ context.found = undefined;
23
+ return request;
24
+ }),
25
+ phase: armada.Phase.REQUEST,
26
+ };
@@ -0,0 +1,2 @@
1
+ import { RequestAgentRoute } from "../types/definitions.js";
2
+ export declare const GetAgents: RequestAgentRoute["intercept"];
@@ -0,0 +1,38 @@
1
+ import { AgentConfigurationSchema } from "agent-def";
2
+ import * as armada from "@artinet/armada";
3
+ import * as sdk from "@artinet/sdk";
4
+ export const GetAgents = {
5
+ trigger: ({ context }) => !!context.target && (context.target.agentIds?.length ?? 0) > 0,
6
+ action: async ({ request, context, }) => {
7
+ for (const agentId of context.target?.agentIds ?? []) {
8
+ await armada.TryFindBase({ request, context }, {
9
+ uri: agentId,
10
+ throwNotFound: false,
11
+ storage: context.storage,
12
+ find: armada.FindAgent,
13
+ });
14
+ if (!context.found || !context.found.results[agentId]) {
15
+ continue;
16
+ }
17
+ const agentConfig = await sdk
18
+ .validateSchema(AgentConfigurationSchema, context.found.results[agentId])
19
+ .catch((error) => {
20
+ sdk.logger.error(`Failed to validate agent configuration: ${agentId}`, error);
21
+ return null;
22
+ });
23
+ if (!agentConfig) {
24
+ continue;
25
+ }
26
+ const agent = await context.load(agentConfig, context);
27
+ if (!agent) {
28
+ continue;
29
+ }
30
+ context.agents = {
31
+ ...context.agents,
32
+ [agentId]: agent,
33
+ };
34
+ }
35
+ return request;
36
+ },
37
+ phase: armada.Phase.REQUEST,
38
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./fetch-agent.js";
2
+ export * from "./get-agents.js";
@@ -0,0 +1,2 @@
1
+ export * from "./fetch-agent.js";
2
+ export * from "./get-agents.js";
@@ -0,0 +1,8 @@
1
+ import { RequestAgentRoute, TestAgentRoute } from "./types/definitions.js";
2
+ export declare const requestAgent: (request: RequestAgentRoute["request"], context: RequestAgentRoute["context"], requestFn?: RequestAgentRoute["implementation"]) => Promise<RequestAgentRoute["response"]>;
3
+ export declare const RequestAgent: RequestAgentRoute["implementation"];
4
+ /**
5
+ * Test agent implementation.
6
+ * @note Similar to RequestAgent, but skips the FetchAgent intercept and uses the testInvoke function that returns a stream of updates.
7
+ */
8
+ export declare const TestAgent: TestAgentRoute["implementation"];
@@ -0,0 +1,16 @@
1
+ import * as armada from "@artinet/armada";
2
+ import { FetchAgent } from "./interceptors/fetch-agent.js";
3
+ import { GetAgents } from "./interceptors/get-agents.js";
4
+ import { requestImplementation } from "./implementation/request.js";
5
+ export const requestAgent = (request, context, requestFn = requestImplementation) => armada.entry({
6
+ request,
7
+ implementation: requestFn,
8
+ intercepts: [FetchAgent, GetAgents],
9
+ context,
10
+ });
11
+ export const RequestAgent = (request, context) => requestAgent(request, context, requestImplementation);
12
+ /**
13
+ * Test agent implementation.
14
+ * @note Similar to RequestAgent, but skips the FetchAgent intercept and uses the testInvoke function that returns a stream of updates.
15
+ */
16
+ export const TestAgent = (request, context) => requestAgent(request, context, requestImplementation);