@fevex/core 0.1.0-alpha.1 → 0.1.0-alpha.10

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 (56) hide show
  1. package/README.md +771 -13
  2. package/dist/agents/index.d.mts +2 -2
  3. package/dist/agents/index.mjs +1 -1
  4. package/dist/artifacts/index.d.mts +2 -0
  5. package/dist/artifacts/index.mjs +2 -0
  6. package/dist/artifacts-gUzemET7.mjs +440 -0
  7. package/dist/channels/index.d.mts +2 -0
  8. package/dist/channels/index.mjs +192 -0
  9. package/dist/evals/index.d.mts +19 -11
  10. package/dist/evals/index.mjs +125 -122
  11. package/dist/fevex-_KOsOsB8.d.mts +129 -0
  12. package/dist/http/index.d.mts +150 -0
  13. package/dist/http/index.mjs +692 -0
  14. package/dist/index-26ilbzAs.d.mts +50 -0
  15. package/dist/index-B8EcvWeN.d.mts +103 -0
  16. package/dist/index-BEqYWean.d.mts +118 -0
  17. package/dist/index-Btth7rdL.d.mts +58 -0
  18. package/dist/{index-QTkd6a7C.d.mts → index-CFzrvDQ0.d.mts} +4 -3
  19. package/dist/index-CIHWc5V1.d.mts +116 -0
  20. package/dist/index-D7r0puBi.d.mts +64 -0
  21. package/dist/index-DHcfIfh-.d.mts +224 -0
  22. package/dist/index-DUhNa7IR.d.mts +73 -0
  23. package/dist/index-lCCFokc6.d.mts +617 -0
  24. package/dist/index.d.mts +22 -10
  25. package/dist/index.mjs +4178 -671
  26. package/dist/knowledge/index.d.mts +2 -0
  27. package/dist/knowledge/index.mjs +289 -0
  28. package/dist/model-stream-JQdHDDcj.mjs +131 -0
  29. package/dist/models/index.d.mts +2 -46
  30. package/dist/observability/index.d.mts +2 -2
  31. package/dist/policies/index.d.mts +1 -1
  32. package/dist/policies/index.mjs +1 -1
  33. package/dist/run-error-Cr17wPGH.mjs +23 -0
  34. package/dist/{model-stream-u2xMsEaf.mjs → run-support-CmZ6Xo6H.mjs} +41 -130
  35. package/dist/runtime/index.d.mts +2 -2
  36. package/dist/runtime/index.mjs +271 -9
  37. package/dist/sandbox/index.d.mts +2 -0
  38. package/dist/sandbox/index.mjs +147 -0
  39. package/dist/teams/index.d.mts +2 -0
  40. package/dist/teams/index.mjs +2 -0
  41. package/dist/teams-Ctz676G4.mjs +82 -0
  42. package/dist/testing/index.d.mts +39 -9
  43. package/dist/testing/index.mjs +512 -28
  44. package/dist/tools/index.d.mts +3 -3
  45. package/dist/tools/index.mjs +442 -2
  46. package/dist/types-CckDlhYo.d.mts +575 -0
  47. package/dist/workflows/index.d.mts +2 -0
  48. package/dist/workflows/index.mjs +6 -0
  49. package/package.json +31 -3
  50. package/dist/exact-definition-NHBBFlFR.d.mts +0 -4
  51. package/dist/fevex-Dz6GBz9o.d.mts +0 -32
  52. package/dist/index-BzxHfyYV.d.mts +0 -23
  53. package/dist/index-CZGyhNIQ.d.mts +0 -47
  54. package/dist/index-C_Zpr13f.d.mts +0 -124
  55. package/dist/index-DGWOGXzc.d.mts +0 -181
  56. package/dist/index-ojCY3lwm.d.mts +0 -79
@@ -0,0 +1,147 @@
1
+ import { relative, resolve } from "node:path";
2
+ import { spawn } from "node:child_process";
3
+ import { realpathSync } from "node:fs";
4
+ //#region src/sandbox/sandbox.ts
5
+ var SandboxError = class extends Error {
6
+ code;
7
+ safeMessage;
8
+ name = "SandboxError";
9
+ constructor(code, safeMessage, options) {
10
+ super(safeMessage, options);
11
+ this.code = code;
12
+ this.safeMessage = safeMessage;
13
+ }
14
+ };
15
+ function sandboxResultToJson(result) {
16
+ return {
17
+ exitCode: result.exitCode,
18
+ stdout: result.stdout,
19
+ stderr: result.stderr,
20
+ durationMs: result.durationMs,
21
+ timedOut: result.timedOut
22
+ };
23
+ }
24
+ //#endregion
25
+ //#region src/sandbox/local-sandbox.ts
26
+ /** Creates a subprocess sandbox restricted to a root directory and command allowlist. */
27
+ function createLocalSandbox(options) {
28
+ if (!options.rootDir.trim()) throw new SandboxError("SANDBOX_INVALID_CONFIG", "Sandbox rootDir must be non-empty");
29
+ if (!options.commands.length || options.commands.some((command) => !command.trim())) throw new SandboxError("SANDBOX_INVALID_CONFIG", "Sandbox commands allowlist must contain non-empty commands");
30
+ const rootDir = realpathSync(resolve(options.rootDir));
31
+ const allowed = new Set(options.commands);
32
+ const defaultTimeoutMs = options.defaultTimeoutMs ?? 1e4;
33
+ const maxOutputBytes = options.maxOutputBytes ?? 64e3;
34
+ return { async run(request) {
35
+ if (request.capabilities?.network) throw new SandboxError("SANDBOX_NETWORK_UNSUPPORTED", "Local sandbox does not support network access");
36
+ const command = request.command;
37
+ if (!allowed.has(command) || !request.capabilities?.process?.commands?.includes(command)) throw new SandboxError("SANDBOX_COMMAND_DENIED", `Command "${command}" is not allowed`);
38
+ const cwd = resolve(rootDir, request.cwd ?? request.capabilities.filesystem?.cwd ?? ".");
39
+ if (!isInside(rootDir, cwd)) throw new SandboxError("SANDBOX_CWD_DENIED", "Sandbox cwd must stay inside rootDir");
40
+ const timeoutMs = request.timeoutMs ?? request.capabilities.resources?.timeoutMs ?? request.capabilities.process.timeoutMs ?? defaultTimeoutMs;
41
+ const outputLimit = request.maxOutputBytes ?? request.capabilities.resources?.maxOutputBytes ?? maxOutputBytes;
42
+ if (!Number.isInteger(timeoutMs) || timeoutMs < 1) throw new SandboxError("SANDBOX_INVALID_REQUEST", "Sandbox timeoutMs must be positive");
43
+ if (!Number.isInteger(outputLimit) || outputLimit < 1) throw new SandboxError("SANDBOX_INVALID_REQUEST", "Sandbox maxOutputBytes must be positive");
44
+ return runProcess({
45
+ command,
46
+ args: request.args ?? [],
47
+ cwd,
48
+ env: {
49
+ ...options.env ?? {},
50
+ ...request.env ?? {}
51
+ },
52
+ input: request.input,
53
+ timeoutMs,
54
+ maxOutputBytes: outputLimit,
55
+ signal: request.signal
56
+ });
57
+ } };
58
+ }
59
+ async function runProcess(options) {
60
+ const started = Date.now();
61
+ let timedOut = false;
62
+ const stdout = {
63
+ text: "",
64
+ bytes: 0
65
+ };
66
+ const stderr = {
67
+ text: "",
68
+ bytes: 0
69
+ };
70
+ return await new Promise((resolvePromise, reject) => {
71
+ options.signal?.throwIfAborted();
72
+ const child = spawn(options.command, [...options.args], {
73
+ cwd: options.cwd,
74
+ env: options.env,
75
+ shell: false,
76
+ stdio: [
77
+ "pipe",
78
+ "pipe",
79
+ "pipe"
80
+ ]
81
+ });
82
+ let aborted = false;
83
+ let killTimer;
84
+ const terminate = () => {
85
+ if (killTimer !== void 0) return;
86
+ child.kill("SIGTERM");
87
+ killTimer = setTimeout(() => child.kill("SIGKILL"), 100);
88
+ };
89
+ const abort = () => {
90
+ aborted = true;
91
+ clearTimeout(timer);
92
+ terminate();
93
+ };
94
+ const timer = setTimeout(() => {
95
+ timedOut = true;
96
+ terminate();
97
+ }, options.timeoutMs);
98
+ const cleanup = () => {
99
+ clearTimeout(timer);
100
+ clearTimeout(killTimer);
101
+ options.signal?.removeEventListener("abort", abort);
102
+ };
103
+ options.signal?.addEventListener("abort", abort, { once: true });
104
+ if (options.signal?.aborted) abort();
105
+ child.stdout.setEncoding("utf8");
106
+ child.stderr.setEncoding("utf8");
107
+ child.stdout.on("data", (chunk) => {
108
+ appendLimited(stdout, String(chunk), options.maxOutputBytes);
109
+ });
110
+ child.stderr.on("data", (chunk) => {
111
+ appendLimited(stderr, String(chunk), options.maxOutputBytes);
112
+ });
113
+ child.on("error", (error) => {
114
+ cleanup();
115
+ reject(new SandboxError("SANDBOX_PROCESS_ERROR", "Sandbox process failed", { cause: error }));
116
+ });
117
+ child.on("close", (exitCode) => {
118
+ cleanup();
119
+ if (aborted) {
120
+ reject(options.signal?.reason ?? new DOMException("Sandbox aborted", "AbortError"));
121
+ return;
122
+ }
123
+ resolvePromise({
124
+ exitCode,
125
+ stdout: stdout.text,
126
+ stderr: stderr.text,
127
+ durationMs: Date.now() - started,
128
+ timedOut
129
+ });
130
+ });
131
+ if (options.input !== void 0) child.stdin.end(options.input);
132
+ else child.stdin.end();
133
+ });
134
+ }
135
+ function appendLimited(output, chunk, maxBytes) {
136
+ const remaining = maxBytes - output.bytes;
137
+ if (remaining <= 0) return;
138
+ const bytes = Buffer.from(chunk).subarray(0, remaining);
139
+ output.bytes += bytes.length;
140
+ output.text += new TextDecoder("utf-8", { ignoreBOM: true }).decode(bytes, { stream: true });
141
+ }
142
+ function isInside(rootDir, value) {
143
+ const path = relative(rootDir, value);
144
+ return path === "" || !path.startsWith("..") && !resolve(path).startsWith("..");
145
+ }
146
+ //#endregion
147
+ export { SandboxError, createLocalSandbox, sandboxResultToJson };
@@ -0,0 +1,2 @@
1
+ import { a as TeamMember, c as defineTeam, i as TeamLimits, n as TeamDelegation, o as TeamStep, r as TeamHandoff, s as TeamTaskResult, t as TeamDefinition } from "../index-26ilbzAs.mjs";
2
+ export { type TeamDefinition, type TeamDelegation, type TeamHandoff, type TeamLimits, type TeamMember, type TeamStep, type TeamTaskResult, defineTeam };
@@ -0,0 +1,2 @@
1
+ import { t as defineTeam } from "../teams-Ctz676G4.mjs";
2
+ export { defineTeam };
@@ -0,0 +1,82 @@
1
+ //#region src/teams/team.ts
2
+ function defineTeam(team) {
3
+ return team;
4
+ }
5
+ /** @internal Compiles teams onto the existing durable workflow engine. */
6
+ function teamAsWorkflow(team) {
7
+ const allowed = /* @__PURE__ */ new Set([team.supervisor, ...team.members.map(({ agent }) => agent)]);
8
+ const limits = team.limits && {
9
+ ...team.limits.maxSteps === void 0 ? {} : { maxSteps: team.limits.maxSteps },
10
+ ...team.limits.maxToolCalls === void 0 ? {} : { maxToolCalls: team.limits.maxToolCalls },
11
+ ...team.limits.maxInputTokens === void 0 ? {} : { maxInputTokens: team.limits.maxInputTokens },
12
+ ...team.limits.maxOutputTokens === void 0 ? {} : { maxOutputTokens: team.limits.maxOutputTokens }
13
+ };
14
+ return {
15
+ name: team.name,
16
+ version: team.version ?? "1",
17
+ inputSchema: team.inputSchema,
18
+ outputSchema: team.outputSchema,
19
+ limits,
20
+ async run(step, input) {
21
+ let delegations = 0;
22
+ const countDelegation = () => {
23
+ delegations += 1;
24
+ if (team.limits?.maxDelegations !== void 0 && delegations > team.limits.maxDelegations) throw new Error(`Team "${team.name}" exceeded maxDelegations limit of ${team.limits.maxDelegations}`);
25
+ };
26
+ const runAgent = async (delegationId, delegation, metadata) => {
27
+ if (!delegationId.trim()) throw new Error("Team delegation id cannot be empty");
28
+ if (!allowed.has(delegation.agent)) throw new Error(`Agent "${delegation.agent}" is not a member of team "${team.name}"`);
29
+ if (delegation.expectedOutput !== void 0 && !delegation.expectedOutput.trim()) throw new Error("Team delegation expectedOutput cannot be empty");
30
+ if (delegation.constraints !== void 0 && (!Array.isArray(delegation.constraints) || delegation.constraints.some((constraint) => typeof constraint !== "string" || !constraint.trim()))) throw new Error("Team delegation constraints must be non-empty strings");
31
+ countDelegation();
32
+ const request = {
33
+ input: delegation.task,
34
+ ...delegation.context === void 0 ? {} : { context: delegation.context },
35
+ ...delegation.limits === void 0 ? {} : { limits: delegation.limits }
36
+ };
37
+ return {
38
+ ...await step.agent(delegationId, delegation.agent, request, { metadata }),
39
+ delegationId,
40
+ agentName: delegation.agent
41
+ };
42
+ };
43
+ return team.run({
44
+ delegate(delegationId, delegation) {
45
+ return runAgent(delegationId, delegation, {
46
+ teamAction: "delegate",
47
+ ...delegation.expectedOutput === void 0 ? {} : { expectedOutput: delegation.expectedOutput },
48
+ ...delegation.constraints === void 0 ? {} : { constraints: delegation.constraints }
49
+ });
50
+ },
51
+ handoff(delegationId, handoff) {
52
+ if (!allowed.has(handoff.from)) throw new Error(`Agent "${handoff.from}" is not a member of team "${team.name}"`);
53
+ if (!handoff.reason.trim()) throw new Error("Team handoff reason cannot be empty");
54
+ return runAgent(delegationId, {
55
+ agent: handoff.to,
56
+ task: handoff.task,
57
+ context: handoff.context,
58
+ limits: handoff.limits,
59
+ expectedOutput: handoff.expectedOutput,
60
+ constraints: handoff.constraints
61
+ }, {
62
+ teamAction: "handoff",
63
+ from: handoff.from,
64
+ reason: handoff.reason,
65
+ ...handoff.expectedOutput === void 0 ? {} : { expectedOutput: handoff.expectedOutput },
66
+ ...handoff.constraints === void 0 ? {} : { constraints: handoff.constraints }
67
+ });
68
+ },
69
+ parallel(stepId, tasks) {
70
+ const width = Object.keys(tasks).length;
71
+ if (team.limits?.maxParallel !== void 0 && width > team.limits.maxParallel) throw new Error(`Team "${team.name}" exceeded maxParallel limit of ${team.limits.maxParallel}`);
72
+ return step.parallel(stepId, tasks, { metadata: {
73
+ teamAction: "merge",
74
+ width
75
+ } });
76
+ }
77
+ }, input);
78
+ }
79
+ };
80
+ }
81
+ //#endregion
82
+ export { teamAsWorkflow as n, defineTeam as t };
@@ -1,18 +1,48 @@
1
- import { m as ToolCall } from "../index-C_Zpr13f.mjs";
2
- import { ModelGateway, ModelInput, ModelResult } from "../models/index.mjs";
3
- import { a as DurableRunStore } from "../index-DGWOGXzc.mjs";
4
- //#region src/testing/index.d.ts
5
- interface FakeModel extends ModelGateway {
6
- readonly calls: readonly ModelInput[];
7
- }
8
- declare function fakeModel(...responses: ModelResult[]): FakeModel;
1
+ import { E as ToolProvider } from "../index-DHcfIfh-.mjs";
2
+ import { a as ModelResult, n as ModelInput, t as ModelGateway } from "../index-D7r0puBi.mjs";
3
+ import { m as ToolCall } from "../types-CckDlhYo.mjs";
4
+ import { j as ElicitationRequest, k as DurableRunStore } from "../index-lCCFokc6.mjs";
5
+ import { f as MemoryStore } from "../index-CIHWc5V1.mjs";
6
+ import { d as ChannelMessage, f as ChannelOutput, o as ChannelElicitationContext, r as ChannelAdapter } from "../index-B8EcvWeN.mjs";
7
+ //#region src/testing/contracts.d.ts
9
8
  interface ModelGatewayContract {
10
9
  output?: unknown;
11
10
  toolCall?: ToolCall;
12
11
  usage?: boolean;
13
12
  error?: Error;
14
13
  }
14
+ interface ChannelAdapterContract<TInput, TOutput> {
15
+ input: TInput;
16
+ message: ChannelMessage;
17
+ output: ChannelOutput;
18
+ delivered: TOutput;
19
+ ignoredInput?: TInput;
20
+ elicitation?: {
21
+ request: ElicitationRequest;
22
+ context: ChannelElicitationContext;
23
+ delivered: TOutput;
24
+ };
25
+ }
26
+ interface ToolProviderContract {
27
+ allowedTool: string;
28
+ input?: unknown;
29
+ output?: unknown;
30
+ disallowedTool?: string;
31
+ safeError?: boolean;
32
+ timeout?: boolean;
33
+ }
34
+ declare function testMemoryStore(store: MemoryStore): Promise<void>;
35
+ declare function testToolProvider(provider: ToolProvider, contract: ToolProviderContract): Promise<void>;
36
+ declare function testChannelAdapter<TInput, TOutput>(adapter: ChannelAdapter<TInput, TOutput>, contract: ChannelAdapterContract<TInput, TOutput>): Promise<void>;
15
37
  declare function testModelGateway(model: ModelGateway, contract?: ModelGatewayContract): Promise<void>;
16
38
  declare function testRunStore(store: DurableRunStore): Promise<void>;
39
+ declare function testRetentionStore(store: DurableRunStore): Promise<void>;
40
+ //#endregion
41
+ //#region src/testing/fake-model.d.ts
42
+ interface FakeModel extends ModelGateway {
43
+ readonly calls: readonly ModelInput[];
44
+ }
45
+ /** Creates a deterministic model gateway for unit tests. */
46
+ declare function fakeModel(...responses: ModelResult[]): FakeModel;
17
47
  //#endregion
18
- export { FakeModel, ModelGatewayContract, fakeModel, testModelGateway, testRunStore };
48
+ export { ChannelAdapterContract, FakeModel, ModelGatewayContract, ToolProviderContract, fakeModel, testChannelAdapter, testMemoryStore, testModelGateway, testRetentionStore, testRunStore, testToolProvider };