@fevex/core 0.1.0-alpha.6 → 0.1.0-alpha.7

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/README.md CHANGED
@@ -978,6 +978,33 @@ const app = createFevex({
978
978
  });
979
979
  ```
980
980
 
981
+ For longer instructions, keep them in an explicit `SKILL.md` file. Only the
982
+ frontmatter metadata enters the prompt; the body loads on demand:
983
+
984
+ ```ts
985
+ import { createAgentsMdContextProvider, loadSkillFile } from '@fevex/core';
986
+
987
+ const refunds = await loadSkillFile('./skills/refunds/SKILL.md');
988
+
989
+ const app = createFevex({
990
+ models,
991
+ contextProviders: [refunds, createAgentsMdContextProvider('./AGENTS.md')],
992
+ agents: [
993
+ defineAgent({
994
+ name: 'support',
995
+ instructions: 'Answer with business context.',
996
+ skills: ['refunds'],
997
+ context: ['agents-md'],
998
+ }),
999
+ ],
1000
+ });
1001
+ ```
1002
+
1003
+ `SKILL.md` uses `name` and `description` frontmatter. The reserved
1004
+ `fevex__load_skill` tool loads the body and lists files under `references/`,
1005
+ `scripts/` and `assets/`; scripts are not executed by the runtime. Paths are
1006
+ explicit, with no automatic discovery.
1007
+
981
1008
  Context providers are lazy per run. Memory is a replaceable store; the built-in
982
1009
  store is in-memory substring search, not embeddings, vector search or durable
983
1010
  storage.
@@ -1,2 +1,2 @@
1
- import { a as ChannelDeliveryOptions, c as ChannelEvent, d as ChannelMessage, f as ChannelOutput, h as ChannelRunResult, i as ChannelContext, l as ChannelEventType, m as ChannelRunOptions, n as handleChannelInput, o as ChannelElicitationContext, p as ChannelRunEvent, r as ChannelAdapter, s as ChannelError, t as deliverChannelRun, u as ChannelFailurePhase } from "../index-DVw0zOc_.mjs";
1
+ import { a as ChannelDeliveryOptions, c as ChannelEvent, d as ChannelMessage, f as ChannelOutput, h as ChannelRunResult, i as ChannelContext, l as ChannelEventType, m as ChannelRunOptions, n as handleChannelInput, o as ChannelElicitationContext, p as ChannelRunEvent, r as ChannelAdapter, s as ChannelError, t as deliverChannelRun, u as ChannelFailurePhase } from "../index-BTD1c4Ys.mjs";
2
2
  export { ChannelAdapter, ChannelContext, ChannelDeliveryOptions, ChannelElicitationContext, ChannelError, ChannelEvent, ChannelEventType, ChannelFailurePhase, ChannelMessage, ChannelOutput, ChannelRunEvent, ChannelRunOptions, ChannelRunResult, deliverChannelRun, handleChannelInput };
@@ -1,7 +1,7 @@
1
1
  import { l as JsonValue, o as ExecutionContext, t as AgentEvent } from "../types-B8laW1hM.mjs";
2
2
  import { r as ModelMetadata, s as ModelUsage } from "../index-BgKFd9yw.mjs";
3
3
  import { t as CostCalculator, u as TraceCost } from "../index-CpLDt6Rw.mjs";
4
- import { t as Fevex } from "../fevex-B4QY5Z6e.mjs";
4
+ import { t as Fevex } from "../fevex-CVMLnZsk.mjs";
5
5
  //#region src/evals/canonical-json.d.ts
6
6
  /** Serializes JSON-like data with stable object-key ordering. */
7
7
  declare function serializeCanonical(value: unknown): string;
@@ -1,7 +1,7 @@
1
1
  import { F as ArtifactStore, f as RunId, o as ExecutionContext, t as AgentEvent } from "./types-B8laW1hM.mjs";
2
2
  import { t as ModelGateway } from "./index-BgKFd9yw.mjs";
3
3
  import { B as TeamRun, C as PurgeRunsResult, F as RunStore, I as Session, J as WorkflowRun, L as SessionId, M as RunRequest, N as RunResult, S as PurgeRunsOptions, a as AgentRun, b as ListEventsOptions, f as CredentialStore, j as RunRecord, t as AgentDefinition, w as ResumeRunResolution } from "./index-CzAi2Y_Z.mjs";
4
- import { r as ContextProvider, s as MemoryStore } from "./index-BJktlD4E.mjs";
4
+ import { c as ContextProvider, f as MemoryStore } from "./index-B0AdFbgr.mjs";
5
5
  import { i as ObservabilityStats, r as ObservabilityOptions } from "./index-CpLDt6Rw.mjs";
6
6
  import { r as Sandbox } from "./index-Df84VWmN.mjs";
7
7
  import { g as ToolDefinition, s as ConnectionDefinition } from "./index-5p3q2yIp.mjs";
@@ -1,7 +1,7 @@
1
1
  import { D as ArtifactCatalog, F as ArtifactStore, f as RunId, k as ArtifactDescriptor, l as JsonValue, o as ExecutionContext, t as AgentEvent } from "../types-B8laW1hM.mjs";
2
2
  import { c as ReasoningEffort } from "../index-BgKFd9yw.mjs";
3
3
  import { B as TeamRun, J as WorkflowRun, L as SessionId, a as AgentRun, j as RunRecord } from "../index-CzAi2Y_Z.mjs";
4
- import { t as Fevex } from "../fevex-B4QY5Z6e.mjs";
4
+ import { t as Fevex } from "../fevex-CVMLnZsk.mjs";
5
5
  //#region src/http/protocol.d.ts
6
6
  declare const FEVEX_HTTP_PROTOCOL_VERSION = "3";
7
7
  declare const FEVEX_HTTP_PROTOCOL_VERSION_HEADER = "Fevex-Protocol-Version";
@@ -0,0 +1,116 @@
1
+ import { l as JsonValue, o as ExecutionContext, s as JsonObject } from "./types-B8laW1hM.mjs";
2
+ import { L as SessionId } from "./index-CzAi2Y_Z.mjs";
3
+ //#region src/knowledge/knowledge.d.ts
4
+ /** Runtime context supplied to knowledge providers and memory stores. */
5
+ interface KnowledgeContext {
6
+ agentName: string;
7
+ input: string;
8
+ sessionId: SessionId;
9
+ context?: ExecutionContext;
10
+ signal?: AbortSignal;
11
+ }
12
+ interface ContextBlock {
13
+ id: string;
14
+ content: string;
15
+ metadata?: JsonObject;
16
+ }
17
+ interface ContextProvider {
18
+ name: string;
19
+ read(context: KnowledgeContext): Promise<ContextBlock[]>;
20
+ }
21
+ interface MemoryQuery {
22
+ query: string;
23
+ limit?: number;
24
+ agentName?: string;
25
+ sessionId?: SessionId;
26
+ namespace?: string;
27
+ actor?: ExecutionContext['actor'];
28
+ }
29
+ interface MemoryWrite {
30
+ content: string;
31
+ agentName?: string;
32
+ sessionId?: SessionId;
33
+ namespace?: string;
34
+ actor?: ExecutionContext['actor'];
35
+ metadata?: JsonObject;
36
+ }
37
+ interface MemoryRecord extends MemoryWrite {
38
+ id: string;
39
+ createdAt: string;
40
+ }
41
+ interface MemoryStore {
42
+ search(query: MemoryQuery, context: KnowledgeContext): Promise<MemoryRecord[]>;
43
+ write(record: MemoryWrite, context: KnowledgeContext): Promise<MemoryRecord>;
44
+ }
45
+ interface SkillDefinition {
46
+ name: string;
47
+ instructions: string;
48
+ resources?: Array<string | JsonValue | {
49
+ id?: string;
50
+ content: string | JsonValue;
51
+ metadata?: JsonObject;
52
+ }>;
53
+ }
54
+ /**
55
+ * Context provider that advertises a skill's metadata and defers its full
56
+ * instructions until the model calls the reserved load-skill tool.
57
+ *
58
+ * The provider name is the skill name referenced from `agent.skills`.
59
+ */
60
+ interface ProgressiveSkillProvider extends ContextProvider {
61
+ /** Short description shown to the model before the skill is loaded. */
62
+ readonly description: string;
63
+ /** Loads the full instructions, or one resource when `resource` is set. */
64
+ load(context: KnowledgeContext, resource?: string): Promise<ContextBlock[]>;
65
+ }
66
+ declare function isProgressiveSkillProvider(provider: ContextProvider): provider is ProgressiveSkillProvider;
67
+ declare function defineContextProvider<T extends ContextProvider>(provider: T): T;
68
+ declare function defineSkill(skill: SkillDefinition): ContextProvider;
69
+ declare function createMemoryContextProvider(options: {
70
+ name?: string;
71
+ store: MemoryStore;
72
+ limit?: number;
73
+ }): ContextProvider;
74
+ //#endregion
75
+ //#region src/knowledge/agents-md.d.ts
76
+ interface AgentsMdOptions {
77
+ /** Explicit path to an `AGENTS.md` file. */
78
+ path: string;
79
+ /** Context provider name; defaults to `agents-md`. */
80
+ name?: string;
81
+ maxBytes?: number;
82
+ }
83
+ /**
84
+ * Reads one explicit `AGENTS.md` file as context.
85
+ *
86
+ * Fevex never walks the filesystem looking for `AGENTS.md`; register one
87
+ * provider per file and reference its name from `agent.context`.
88
+ */
89
+ declare function createAgentsMdContextProvider(options: AgentsMdOptions | string): ContextProvider;
90
+ //#endregion
91
+ //#region src/knowledge/in-memory-memory-store.d.ts
92
+ /** Volatile keyword-search memory store for tests and local development. */
93
+ declare class InMemoryMemoryStore implements MemoryStore {
94
+ #private;
95
+ search(query: MemoryQuery, context: KnowledgeContext): Promise<MemoryRecord[]>;
96
+ write(record: MemoryWrite, context: KnowledgeContext): Promise<MemoryRecord>;
97
+ }
98
+ //#endregion
99
+ //#region src/knowledge/skill-file.d.ts
100
+ interface LoadSkillFileOptions {
101
+ /** Maximum size of the `SKILL.md` file. */
102
+ maxBytes?: number;
103
+ /** Maximum size of one resource loaded on demand. */
104
+ maxResourceBytes?: number;
105
+ }
106
+ /**
107
+ * Loads one explicit `SKILL.md` file.
108
+ *
109
+ * Only `name` and `description` are advertised up front. The body and any
110
+ * files under `references/`, `scripts/` or `assets/` load on demand.
111
+ */
112
+ declare function loadSkillFile(path: string, options?: LoadSkillFileOptions): Promise<ProgressiveSkillProvider>;
113
+ /** Loads several explicit `SKILL.md` files; it never scans directories. */
114
+ declare function loadSkillFiles(paths: readonly string[], options?: LoadSkillFileOptions): Promise<ProgressiveSkillProvider[]>;
115
+ //#endregion
116
+ export { defineContextProvider as _, AgentsMdOptions as a, ContextProvider as c, MemoryRecord as d, MemoryStore as f, createMemoryContextProvider as g, SkillDefinition as h, InMemoryMemoryStore as i, KnowledgeContext as l, ProgressiveSkillProvider as m, loadSkillFile as n, createAgentsMdContextProvider as o, MemoryWrite as p, loadSkillFiles as r, ContextBlock as s, LoadSkillFileOptions as t, MemoryQuery as u, defineSkill as v, isProgressiveSkillProvider as y };
@@ -1,6 +1,6 @@
1
1
  import { f as RunId, o as ExecutionContext, s as JsonObject, t as AgentEvent } from "./types-B8laW1hM.mjs";
2
2
  import { L as SessionId, a as AgentRun, h as ElicitationRequest } from "./index-CzAi2Y_Z.mjs";
3
- import { t as Fevex } from "./fevex-B4QY5Z6e.mjs";
3
+ import { t as Fevex } from "./fevex-CVMLnZsk.mjs";
4
4
  //#region src/channels/channel.d.ts
5
5
  interface ChannelMessage {
6
6
  id: string;
package/dist/index.d.mts CHANGED
@@ -1,14 +1,14 @@
1
1
  import { A as ArtifactError, C as FileSystemArtifactStore, D as ArtifactCatalog, E as CatalogedArtifactStoreOptions, F as ArtifactStore, I as ArtifactStoreContext, L as ArtifactWrite, M as ArtifactId, N as ArtifactQuery, O as ArtifactContent, P as ArtifactRecord, R as artifactTenantId, S as InMemoryArtifactCatalog, T as CatalogedArtifactStore, _ as S3ArtifactStore, a as AgentMessageRole, b as InMemoryArtifactStore, c as JsonPrimitive, d as PROVIDER_SCHEMA_UNSUPPORTED, f as RunId, g as ToolSpec, h as ToolEventSource, i as AgentMessage, j as ArtifactErrorCode, k as ArtifactDescriptor, l as JsonValue, m as ToolCall, n as AgentEventPayloads, o as ExecutionContext, p as SCHEMA_NOT_TRANSPORTABLE, r as AgentEventType, s as JsonObject, t as AgentEvent, u as PROVIDER_REASONING_UNSUPPORTED, v as S3ArtifactStoreOptions, w as FileSystemArtifactStoreOptions, x as InMemoryArtifactStoreOptions, y as S3ObjectClient, z as assertArtifactId } from "./types-B8laW1hM.mjs";
2
2
  import { a as ModelResult, c as ReasoningEffort, i as ModelRef, l as ToolChoice, n as ModelInput, o as ModelStreamEvent, r as ModelMetadata, s as ModelUsage, t as ModelGateway } from "./index-BgKFd9yw.mjs";
3
3
  import { $ as validateListEventsOptions, A as RunPause, B as TeamRun, C as PurgeRunsResult, D as RunCheckpoint, E as RetainableRunStore, F as RunStore, G as WorkflowBudgetUsage, H as ToolExecutionRecord, I as Session, J as WorkflowRun, K as WorkflowCheckpoint, L as SessionId, M as RunRequest, N as RunResult, O as RunCorrelation, P as RunStatus, Q as isRetainableRunStore, R as StoredRunCheckpoint, S as PurgeRunsOptions, T as RetainableRunStatus, U as ToolExecutionResolution, V as TimerResolution, W as ToolExecutionStatus, X as WorkflowWaitRecord, Y as WorkflowStepRecord, Z as isDurableRunStore, _ as EventResolution, a as AgentRun, b as ListEventsOptions, c as ApprovalRequest, d as CoordinatorRun, et as validatePurgeRunsOptions, f as CredentialStore, g as ElicitationResolution, h as ElicitationRequest, i as InMemoryRunStore, j as RunRecord, k as RunLease, l as ApprovalResolution, m as ElicitationMode, n as AgentLimits, o as AgentRunPause, p as DurableRunStore, q as WorkflowCompensationRecord, r as defineAgent, s as ApprovalMode, t as AgentDefinition, u as CoordinatorCheckpoint, v as ExecutionCommit, w as ResumeRunResolution, x as PendingToolExecution, y as ExecutionCreate, z as TeamCheckpoint } from "./index-CzAi2Y_Z.mjs";
4
- import { a as MemoryQuery, c as MemoryWrite, d as defineContextProvider, f as defineSkill, i as KnowledgeContext, l as SkillDefinition, n as ContextBlock, o as MemoryRecord, r as ContextProvider, s as MemoryStore, t as InMemoryMemoryStore, u as createMemoryContextProvider } from "./index-BJktlD4E.mjs";
4
+ import { _ as defineContextProvider, a as AgentsMdOptions, c as ContextProvider, d as MemoryRecord, f as MemoryStore, g as createMemoryContextProvider, h as SkillDefinition, i as InMemoryMemoryStore, l as KnowledgeContext, m as ProgressiveSkillProvider, n as loadSkillFile, o as createAgentsMdContextProvider, p as MemoryWrite, r as loadSkillFiles, s as ContextBlock, t as LoadSkillFileOptions, u as MemoryQuery, v as defineSkill, y as isProgressiveSkillProvider } from "./index-B0AdFbgr.mjs";
5
5
  import { a as SandboxError, c as sandboxResultToJson, i as SandboxCapabilities, n as createLocalSandbox, o as SandboxRunRequest, r as Sandbox, s as SandboxRunResult, t as LocalSandboxOptions } from "./index-Df84VWmN.mjs";
6
6
  import { C as toToolSpec, S as defineTool, _ as ToolExecutionContext, a as compileFevexJsonSchema, b as ToolRetryPolicy, c as ConnectionToolPolicy, d as ToolProvider, f as ToolProviderContext, g as ToolDefinition, h as ToolApproval, i as FevexJsonSchemaValidator, l as IntegrationError, m as defineConnection, n as FevexJsonSchemaProfileLimits, o as validateFevexJsonSchemaProfile, p as ToolProviderTool, r as FevexJsonSchemaProfileOptions, s as ConnectionDefinition, t as FEVEX_JSON_SCHEMA_PROFILE_VERSION, u as IntegrationErrorCategory, v as ToolIdempotency, x as ToolRisk, y as ToolResult } from "./index-5p3q2yIp.mjs";
7
7
  import { i as definePolicy, n as PolicyDecision, r as PolicyDefinition, t as PolicyAuthorization } from "./index-CbACw6xZ.mjs";
8
8
  import { a as WorkflowStep, c as defineWorkflow, i as WorkflowEventResult, n as WorkflowDefinition, o as WorkflowStepContext, r as WorkflowEventDefinition, s as WorkflowStepOptions, t as WorkflowAgentResult } from "./index-CseuTR-F.mjs";
9
9
  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-1cHr7KB_.mjs";
10
- import { a as FevexLimits, c as createFevex, i as FevexConfig, n as FevexAdmission, o as FevexShutdownOptions, r as FevexAdmissionRequest, s as FevexShutdownResult, t as Fevex } from "./fevex-B4QY5Z6e.mjs";
11
- import { a as ChannelDeliveryOptions, c as ChannelEvent, d as ChannelMessage, f as ChannelOutput, h as ChannelRunResult, i as ChannelContext, l as ChannelEventType, m as ChannelRunOptions, n as handleChannelInput, o as ChannelElicitationContext, p as ChannelRunEvent, r as ChannelAdapter, s as ChannelError, t as deliverChannelRun, u as ChannelFailurePhase } from "./index-DVw0zOc_.mjs";
10
+ import { a as FevexLimits, c as createFevex, i as FevexConfig, n as FevexAdmission, o as FevexShutdownOptions, r as FevexAdmissionRequest, s as FevexShutdownResult, t as Fevex } from "./fevex-CVMLnZsk.mjs";
11
+ import { a as ChannelDeliveryOptions, c as ChannelEvent, d as ChannelMessage, f as ChannelOutput, h as ChannelRunResult, i as ChannelContext, l as ChannelEventType, m as ChannelRunOptions, n as handleChannelInput, o as ChannelElicitationContext, p as ChannelRunEvent, r as ChannelAdapter, s as ChannelError, t as deliverChannelRun, u as ChannelFailurePhase } from "./index-BTD1c4Ys.mjs";
12
12
  //#region src/configuration-error.d.ts
13
13
  /**
14
14
  * Composition error codes.
@@ -39,4 +39,4 @@ declare class RunPausedError extends FevexRunError {
39
39
  constructor(runId: RunId, pause: RunPause);
40
40
  }
41
41
  //#endregion
42
- export { AgentDefinition, AgentEvent, AgentEventPayloads, AgentEventType, AgentLimits, AgentMessage, AgentMessageRole, AgentRun, AgentRunPause, ApprovalMode, ApprovalRequest, ApprovalResolution, ArtifactCatalog, ArtifactContent, ArtifactDescriptor, ArtifactError, ArtifactErrorCode, ArtifactId, ArtifactQuery, ArtifactRecord, ArtifactStore, ArtifactStoreContext, ArtifactWrite, CatalogedArtifactStore, CatalogedArtifactStoreOptions, ChannelAdapter, ChannelContext, ChannelDeliveryOptions, ChannelElicitationContext, ChannelError, ChannelEvent, ChannelEventType, ChannelFailurePhase, ChannelMessage, ChannelOutput, ChannelRunEvent, ChannelRunOptions, ChannelRunResult, ConnectionDefinition, ConnectionToolPolicy, ContextBlock, ContextProvider, CoordinatorCheckpoint, CoordinatorRun, CredentialStore, DurableRunStore, ElicitationMode, ElicitationRequest, ElicitationResolution, EventResolution, ExecutionCommit, ExecutionContext, ExecutionCreate, FEVEX_JSON_SCHEMA_PROFILE_VERSION, Fevex, FevexAdmission, FevexAdmissionRequest, FevexConfig, FevexConfigurationError, FevexConfigurationErrorCode, FevexJsonSchemaProfileLimits, FevexJsonSchemaProfileOptions, FevexJsonSchemaValidator, FevexLimits, FevexRunError, FevexRunErrorCode, FevexShutdownOptions, FevexShutdownResult, FileSystemArtifactStore, FileSystemArtifactStoreOptions, InMemoryArtifactCatalog, InMemoryArtifactStore, InMemoryArtifactStoreOptions, InMemoryMemoryStore, InMemoryRunStore, IntegrationError, IntegrationErrorCategory, JsonObject, JsonPrimitive, JsonValue, KnowledgeContext, ListEventsOptions, LocalSandboxOptions, MemoryQuery, MemoryRecord, MemoryStore, MemoryWrite, ModelGateway, ModelInput, ModelMetadata, ModelRef, ModelResult, ModelStreamEvent, ModelUsage, PROVIDER_REASONING_UNSUPPORTED, PROVIDER_SCHEMA_UNSUPPORTED, PendingToolExecution, PolicyAuthorization, PolicyDecision, PolicyDefinition, PurgeRunsOptions, PurgeRunsResult, ReasoningEffort, ResumeRunResolution, RetainableRunStatus, RetainableRunStore, RunCheckpoint, RunCorrelation, RunId, RunLease, RunPause, RunPausedError, RunRecord, RunRequest, RunResult, RunStatus, RunStore, S3ArtifactStore, S3ArtifactStoreOptions, S3ObjectClient, SCHEMA_NOT_TRANSPORTABLE, Sandbox, SandboxCapabilities, SandboxError, SandboxRunRequest, SandboxRunResult, Session, SessionId, SkillDefinition, StoredRunCheckpoint, TeamCheckpoint, type TeamDefinition, type TeamDelegation, type TeamHandoff, type TeamLimits, type TeamMember, TeamRun, type TeamStep, type TeamTaskResult, TimerResolution, ToolApproval, ToolCall, ToolChoice, ToolDefinition, ToolEventSource, ToolExecutionContext, ToolExecutionRecord, ToolExecutionResolution, ToolExecutionStatus, ToolIdempotency, ToolProvider, ToolProviderContext, ToolProviderTool, ToolResult, ToolRetryPolicy, ToolRisk, ToolSpec, WorkflowAgentResult, WorkflowBudgetUsage, WorkflowCheckpoint, WorkflowCompensationRecord, WorkflowDefinition, WorkflowEventDefinition, WorkflowEventResult, WorkflowRun, WorkflowStep, WorkflowStepContext, WorkflowStepOptions, WorkflowStepRecord, WorkflowWaitRecord, artifactTenantId, assertArtifactId, compileFevexJsonSchema, createFevex, createLocalSandbox, createMemoryContextProvider, defineAgent, defineConnection, defineContextProvider, definePolicy, defineSkill, defineTeam, defineTool, defineWorkflow, deliverChannelRun, handleChannelInput, isDurableRunStore, isRetainableRunStore, sandboxResultToJson, toToolSpec, validateFevexJsonSchemaProfile, validateListEventsOptions, validatePurgeRunsOptions };
42
+ export { AgentDefinition, AgentEvent, AgentEventPayloads, AgentEventType, AgentLimits, AgentMessage, AgentMessageRole, AgentRun, AgentRunPause, AgentsMdOptions, ApprovalMode, ApprovalRequest, ApprovalResolution, ArtifactCatalog, ArtifactContent, ArtifactDescriptor, ArtifactError, ArtifactErrorCode, ArtifactId, ArtifactQuery, ArtifactRecord, ArtifactStore, ArtifactStoreContext, ArtifactWrite, CatalogedArtifactStore, CatalogedArtifactStoreOptions, ChannelAdapter, ChannelContext, ChannelDeliveryOptions, ChannelElicitationContext, ChannelError, ChannelEvent, ChannelEventType, ChannelFailurePhase, ChannelMessage, ChannelOutput, ChannelRunEvent, ChannelRunOptions, ChannelRunResult, ConnectionDefinition, ConnectionToolPolicy, ContextBlock, ContextProvider, CoordinatorCheckpoint, CoordinatorRun, CredentialStore, DurableRunStore, ElicitationMode, ElicitationRequest, ElicitationResolution, EventResolution, ExecutionCommit, ExecutionContext, ExecutionCreate, FEVEX_JSON_SCHEMA_PROFILE_VERSION, Fevex, FevexAdmission, FevexAdmissionRequest, FevexConfig, FevexConfigurationError, FevexConfigurationErrorCode, FevexJsonSchemaProfileLimits, FevexJsonSchemaProfileOptions, FevexJsonSchemaValidator, FevexLimits, FevexRunError, FevexRunErrorCode, FevexShutdownOptions, FevexShutdownResult, FileSystemArtifactStore, FileSystemArtifactStoreOptions, InMemoryArtifactCatalog, InMemoryArtifactStore, InMemoryArtifactStoreOptions, InMemoryMemoryStore, InMemoryRunStore, IntegrationError, IntegrationErrorCategory, JsonObject, JsonPrimitive, JsonValue, KnowledgeContext, ListEventsOptions, LoadSkillFileOptions, LocalSandboxOptions, MemoryQuery, MemoryRecord, MemoryStore, MemoryWrite, ModelGateway, ModelInput, ModelMetadata, ModelRef, ModelResult, ModelStreamEvent, ModelUsage, PROVIDER_REASONING_UNSUPPORTED, PROVIDER_SCHEMA_UNSUPPORTED, PendingToolExecution, PolicyAuthorization, PolicyDecision, PolicyDefinition, ProgressiveSkillProvider, PurgeRunsOptions, PurgeRunsResult, ReasoningEffort, ResumeRunResolution, RetainableRunStatus, RetainableRunStore, RunCheckpoint, RunCorrelation, RunId, RunLease, RunPause, RunPausedError, RunRecord, RunRequest, RunResult, RunStatus, RunStore, S3ArtifactStore, S3ArtifactStoreOptions, S3ObjectClient, SCHEMA_NOT_TRANSPORTABLE, Sandbox, SandboxCapabilities, SandboxError, SandboxRunRequest, SandboxRunResult, Session, SessionId, SkillDefinition, StoredRunCheckpoint, TeamCheckpoint, type TeamDefinition, type TeamDelegation, type TeamHandoff, type TeamLimits, type TeamMember, TeamRun, type TeamStep, type TeamTaskResult, TimerResolution, ToolApproval, ToolCall, ToolChoice, ToolDefinition, ToolEventSource, ToolExecutionContext, ToolExecutionRecord, ToolExecutionResolution, ToolExecutionStatus, ToolIdempotency, ToolProvider, ToolProviderContext, ToolProviderTool, ToolResult, ToolRetryPolicy, ToolRisk, ToolSpec, WorkflowAgentResult, WorkflowBudgetUsage, WorkflowCheckpoint, WorkflowCompensationRecord, WorkflowDefinition, WorkflowEventDefinition, WorkflowEventResult, WorkflowRun, WorkflowStep, WorkflowStepContext, WorkflowStepOptions, WorkflowStepRecord, WorkflowWaitRecord, artifactTenantId, assertArtifactId, compileFevexJsonSchema, createAgentsMdContextProvider, createFevex, createLocalSandbox, createMemoryContextProvider, defineAgent, defineConnection, defineContextProvider, definePolicy, defineSkill, defineTeam, defineTool, defineWorkflow, deliverChannelRun, handleChannelInput, isDurableRunStore, isProgressiveSkillProvider, isRetainableRunStore, loadSkillFile, loadSkillFiles, sandboxResultToJson, toToolSpec, validateFevexJsonSchemaProfile, validateListEventsOptions, validatePurgeRunsOptions };
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { defineAgent } from "./agents/index.mjs";
2
2
  import { a as CatalogedArtifactStore, c as assertArtifactId, i as FileSystemArtifactStore, n as InMemoryArtifactStore, o as ArtifactError, r as InMemoryArtifactCatalog, s as artifactTenantId, t as S3ArtifactStore } from "./artifacts-gUzemET7.mjs";
3
3
  import { n as RunPausedError, t as FevexRunError } from "./run-error-Cr17wPGH.mjs";
4
4
  import { ChannelError, deliverChannelRun, handleChannelInput } from "./channels/index.mjs";
5
- import { InMemoryMemoryStore, createMemoryContextProvider, defineContextProvider, defineSkill } from "./knowledge/index.mjs";
5
+ import { InMemoryMemoryStore, createAgentsMdContextProvider, createMemoryContextProvider, defineContextProvider, defineSkill, isProgressiveSkillProvider, loadSkillFile, loadSkillFiles } from "./knowledge/index.mjs";
6
6
  import { n as teamAsWorkflow, t as defineTeam } from "./teams-Ctz676G4.mjs";
7
7
  import { InMemoryRunStore, isDurableRunStore, isRetainableRunStore, validateListEventsOptions, validatePurgeRunsOptions } from "./runtime/index.mjs";
8
8
  import { FEVEX_JSON_SCHEMA_PROFILE_VERSION, IntegrationError, compileFevexJsonSchema, defineConnection, defineTool, toToolSpec, validateFevexJsonSchemaProfile } from "./tools/index.mjs";
@@ -649,6 +649,8 @@ const LEASE_MS = 3e4;
649
649
  const LEASE_RENEW_MS = 1e4;
650
650
  /** Reserved name of the internal elicitation tool exposed to the model. */
651
651
  const ELICIT_TOOL_NAME = "fevex__elicit";
652
+ /** Reserved name of the internal progressive skill loader exposed to the model. */
653
+ const LOAD_SKILL_TOOL_NAME = "fevex__load_skill";
652
654
  //#endregion
653
655
  //#region src/internal/run-helpers.ts
654
656
  function redact(message, secrets) {
@@ -1179,26 +1181,50 @@ function createAgentEngine(composition, core) {
1179
1181
  description: remote.description
1180
1182
  } : tool, inputSchema);
1181
1183
  }));
1182
- const allTools = currentElicitationMode === "pause" ? [...agentTools, {
1183
- name: ELICIT_TOOL_NAME,
1184
- description: "Request external information required to continue this run. Use prompt for explanatory text shown outside the form. Put short field labels in responseSchema property titles and optional field help in property descriptions.",
1184
+ const progressiveSkills = (agent.skills ?? []).map((skillName) => contextProviders.get(skillName)).filter((provider) => provider !== void 0 && isProgressiveSkillProvider(provider));
1185
+ const skillTool = progressiveSkills.length === 0 ? void 0 : {
1186
+ name: LOAD_SKILL_TOOL_NAME,
1187
+ description: `Load the full instructions for one of this agent's skills. Available skills: ${progressiveSkills.map((skill) => skill.name).join(", ")}. Pass a resource path from the loaded skill to read one resource.`,
1185
1188
  inputSchema: {
1186
1189
  type: "object",
1187
1190
  properties: {
1188
- prompt: {
1191
+ name: {
1189
1192
  type: "string",
1190
- description: "Explanatory text for the user; do not duplicate field labels here."
1193
+ enum: progressiveSkills.map((skill) => skill.name)
1191
1194
  },
1192
- responseSchema: {
1193
- type: "object",
1194
- description: "JSON Schema for the expected response. Each property should include a short title for the form label and may include a description for field help."
1195
- },
1196
- expiresAt: { type: "string" }
1195
+ resource: {
1196
+ type: "string",
1197
+ description: "Optional resource path returned by a previous load."
1198
+ }
1197
1199
  },
1198
- required: ["prompt", "responseSchema"],
1200
+ required: ["name"],
1199
1201
  additionalProperties: false
1200
1202
  }
1201
- }] : agentTools;
1203
+ };
1204
+ const allTools = [
1205
+ ...agentTools,
1206
+ ...skillTool === void 0 ? [] : [skillTool],
1207
+ ...currentElicitationMode === "pause" ? [{
1208
+ name: ELICIT_TOOL_NAME,
1209
+ description: "Request external information required to continue this run. Use prompt for explanatory text shown outside the form. Put short field labels in responseSchema property titles and optional field help in property descriptions.",
1210
+ inputSchema: {
1211
+ type: "object",
1212
+ properties: {
1213
+ prompt: {
1214
+ type: "string",
1215
+ description: "Explanatory text for the user; do not duplicate field labels here."
1216
+ },
1217
+ responseSchema: {
1218
+ type: "object",
1219
+ description: "JSON Schema for the expected response. Each property should include a short title for the form label and may include a description for field help."
1220
+ },
1221
+ expiresAt: { type: "string" }
1222
+ },
1223
+ required: ["prompt", "responseSchema"],
1224
+ additionalProperties: false
1225
+ }
1226
+ }] : []
1227
+ ];
1202
1228
  const effectiveLimits = state.checkpoint?.limits ?? combineLimits(agent.limits, request.limits);
1203
1229
  const maxSteps = effectiveLimits?.maxSteps ?? 8;
1204
1230
  const maxToolCalls = effectiveLimits?.maxToolCalls ?? 16;
@@ -1287,6 +1313,57 @@ function createAgentEngine(composition, core) {
1287
1313
  assertContinuationBudget(name, "maxInputTokens", "inputTokens", effectiveLimits?.maxInputTokens, usage);
1288
1314
  assertContinuationBudget(name, "maxOutputTokens", "outputTokens", effectiveLimits?.maxOutputTokens, usage);
1289
1315
  if (result.toolCalls.length > maxToolCalls - toolCallCount) throw new Error(`Agent "${name}" exceeded maxToolCalls limit of ${maxToolCalls}`);
1316
+ const loadSkillCall = progressiveSkills.length === 0 ? void 0 : result.toolCalls.find((call) => call.name === LOAD_SKILL_TOOL_NAME);
1317
+ if (loadSkillCall) {
1318
+ if (result.toolCalls.length !== 1) throw new Error(`${LOAD_SKILL_TOOL_NAME} must be the only tool call in a model turn`);
1319
+ if (!loadSkillCall.id?.trim()) throw new Error("Tool call id cannot be empty");
1320
+ if (seenToolCallIds.has(loadSkillCall.id)) throw new Error(`Tool call id "${loadSkillCall.id}" is duplicated in run "${state.run.id}"`);
1321
+ if (toolCallCount + 1 > maxToolCalls) throw new Error(`Agent "${name}" exceeded maxToolCalls limit of ${maxToolCalls}`);
1322
+ const rawInput = toJsonValue(loadSkillCall.input, `Input for tool "${LOAD_SKILL_TOOL_NAME}" must be JSON-serializable`);
1323
+ const skillInput = readSkillInput(rawInput);
1324
+ const skill = progressiveSkills.find((item) => item.name === skillInput.name);
1325
+ if (!skill) throw new Error(`Skill "${skillInput.name}" is not available to agent "${name}"`);
1326
+ seenToolCallIds.add(loadSkillCall.id);
1327
+ messages.push({
1328
+ role: "assistant",
1329
+ content: result.output === void 0 ? "" : serializeValue(result.output, `Model output for agent "${name}" must be serializable`),
1330
+ toolCalls: [{
1331
+ ...loadSkillCall,
1332
+ input: rawInput
1333
+ }]
1334
+ });
1335
+ yield await emit("tool.started", {
1336
+ step,
1337
+ toolCallId: loadSkillCall.id,
1338
+ toolName: LOAD_SKILL_TOOL_NAME
1339
+ });
1340
+ let blocks;
1341
+ try {
1342
+ blocks = await abortable(() => skill.load(knowledgeContext(state, inputContent), skillInput.resource), request.signal);
1343
+ } catch (error) {
1344
+ yield await emit("tool.failed", {
1345
+ step,
1346
+ toolCallId: loadSkillCall.id,
1347
+ toolName: LOAD_SKILL_TOOL_NAME,
1348
+ error: toErrorMessage(error)
1349
+ });
1350
+ throw new Error(`Skill provider "${skill.name}" failed: ${toErrorMessage(error)}`, { cause: error });
1351
+ }
1352
+ messages.push({
1353
+ role: "tool",
1354
+ name: LOAD_SKILL_TOOL_NAME,
1355
+ toolCallId: loadSkillCall.id,
1356
+ content: blocks.filter((block) => block.content.trim()).map((block) => `[Skill: ${skill.name}/${block.id}]\n${block.content}`).join("\n\n")
1357
+ });
1358
+ yield await emit("tool.completed", {
1359
+ step,
1360
+ toolCallId: loadSkillCall.id,
1361
+ toolName: LOAD_SKILL_TOOL_NAME
1362
+ });
1363
+ toolCallCount += 1;
1364
+ step += 1;
1365
+ continue;
1366
+ }
1290
1367
  const elicitationCall = result.toolCalls.find(isElicitationToolCall);
1291
1368
  if (elicitationCall) {
1292
1369
  if (!isDurableRunStore(runStore)) throw new FevexRunError("DURABLE_STORE_REQUIRED", "Elicitation requires a DurableRunStore", state.run.id);
@@ -2036,6 +2113,18 @@ function createAgentEngine(composition, core) {
2036
2113
  cancelStoredAgent
2037
2114
  };
2038
2115
  }
2116
+ function readSkillInput(input) {
2117
+ if (typeof input !== "object" || input === null || Array.isArray(input)) throw new TypeError(`${LOAD_SKILL_TOOL_NAME} input must be an object`);
2118
+ const record = input;
2119
+ const name = record.name;
2120
+ const resource = record.resource;
2121
+ if (typeof name !== "string" || !name.trim()) throw new TypeError(`${LOAD_SKILL_TOOL_NAME} name must be a non-empty string`);
2122
+ if (resource !== void 0 && (typeof resource !== "string" || !resource.trim())) throw new TypeError(`${LOAD_SKILL_TOOL_NAME} resource must be a non-empty string`);
2123
+ return {
2124
+ name: name.trim(),
2125
+ ...resource === void 0 ? {} : { resource: resource.trim() }
2126
+ };
2127
+ }
2039
2128
  function scopedArtifacts(store, options) {
2040
2129
  const scopedContext = (value) => {
2041
2130
  const contextTenant = options.request.context?.attributes?.tenantId;
@@ -4344,4 +4433,4 @@ function createFevex(config) {
4344
4433
  return createRuntime(createComposition(config));
4345
4434
  }
4346
4435
  //#endregion
4347
- export { ArtifactError, CatalogedArtifactStore, ChannelError, FEVEX_JSON_SCHEMA_PROFILE_VERSION, FevexConfigurationError, FevexRunError, FileSystemArtifactStore, InMemoryArtifactCatalog, InMemoryArtifactStore, InMemoryMemoryStore, InMemoryRunStore, IntegrationError, PROVIDER_REASONING_UNSUPPORTED, PROVIDER_SCHEMA_UNSUPPORTED, RunPausedError, S3ArtifactStore, SCHEMA_NOT_TRANSPORTABLE, SandboxError, artifactTenantId, assertArtifactId, compileFevexJsonSchema, createFevex, createLocalSandbox, createMemoryContextProvider, defineAgent, defineConnection, defineContextProvider, definePolicy, defineSkill, defineTeam, defineTool, defineWorkflow, deliverChannelRun, handleChannelInput, isDurableRunStore, isRetainableRunStore, sandboxResultToJson, toToolSpec, validateFevexJsonSchemaProfile, validateListEventsOptions, validatePurgeRunsOptions };
4436
+ export { ArtifactError, CatalogedArtifactStore, ChannelError, FEVEX_JSON_SCHEMA_PROFILE_VERSION, FevexConfigurationError, FevexRunError, FileSystemArtifactStore, InMemoryArtifactCatalog, InMemoryArtifactStore, InMemoryMemoryStore, InMemoryRunStore, IntegrationError, PROVIDER_REASONING_UNSUPPORTED, PROVIDER_SCHEMA_UNSUPPORTED, RunPausedError, S3ArtifactStore, SCHEMA_NOT_TRANSPORTABLE, SandboxError, artifactTenantId, assertArtifactId, compileFevexJsonSchema, createAgentsMdContextProvider, createFevex, createLocalSandbox, createMemoryContextProvider, defineAgent, defineConnection, defineContextProvider, definePolicy, defineSkill, defineTeam, defineTool, defineWorkflow, deliverChannelRun, handleChannelInput, isDurableRunStore, isProgressiveSkillProvider, isRetainableRunStore, loadSkillFile, loadSkillFiles, sandboxResultToJson, toToolSpec, validateFevexJsonSchemaProfile, validateListEventsOptions, validatePurgeRunsOptions };
@@ -1,2 +1,2 @@
1
- import { a as MemoryQuery, c as MemoryWrite, d as defineContextProvider, f as defineSkill, i as KnowledgeContext, l as SkillDefinition, n as ContextBlock, o as MemoryRecord, r as ContextProvider, s as MemoryStore, t as InMemoryMemoryStore, u as createMemoryContextProvider } from "../index-BJktlD4E.mjs";
2
- export { ContextBlock, ContextProvider, InMemoryMemoryStore, KnowledgeContext, MemoryQuery, MemoryRecord, MemoryStore, MemoryWrite, SkillDefinition, createMemoryContextProvider, defineContextProvider, defineSkill };
1
+ import { _ as defineContextProvider, a as AgentsMdOptions, c as ContextProvider, d as MemoryRecord, f as MemoryStore, g as createMemoryContextProvider, h as SkillDefinition, i as InMemoryMemoryStore, l as KnowledgeContext, m as ProgressiveSkillProvider, n as loadSkillFile, o as createAgentsMdContextProvider, p as MemoryWrite, r as loadSkillFiles, s as ContextBlock, t as LoadSkillFileOptions, u as MemoryQuery, v as defineSkill, y as isProgressiveSkillProvider } from "../index-B0AdFbgr.mjs";
2
+ export { AgentsMdOptions, ContextBlock, ContextProvider, InMemoryMemoryStore, KnowledgeContext, LoadSkillFileOptions, MemoryQuery, MemoryRecord, MemoryStore, MemoryWrite, ProgressiveSkillProvider, SkillDefinition, createAgentsMdContextProvider, createMemoryContextProvider, defineContextProvider, defineSkill, isProgressiveSkillProvider, loadSkillFile, loadSkillFiles };
@@ -1,39 +1,10 @@
1
- //#region src/knowledge/in-memory-memory-store.ts
2
- /** Volatile keyword-search memory store for tests and local development. */
3
- var InMemoryMemoryStore = class {
4
- #records = /* @__PURE__ */ new Map();
5
- async search(query, context) {
6
- context.signal?.throwIfAborted();
7
- const terms = query.query.toLowerCase().split(/\s+/).filter(Boolean);
8
- const scored = [...this.#records.values()].filter((record) => matchesScope(record, query)).map((record) => ({
9
- record,
10
- score: score(record.content, terms)
11
- })).filter(({ score }) => !terms.length || score > 0).sort((left, right) => right.score - left.score || right.record.createdAt.localeCompare(left.record.createdAt));
12
- return scored.slice(0, query.limit ?? scored.length).map(({ record }) => structuredClone(record));
13
- }
14
- async write(record, context) {
15
- context.signal?.throwIfAborted();
16
- const saved = {
17
- id: crypto.randomUUID(),
18
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
19
- ...structuredClone(record)
20
- };
21
- this.#records.set(saved.id, saved);
22
- return structuredClone(saved);
23
- }
24
- };
25
- function matchesScope(record, query) {
26
- return matches(record.agentName, query.agentName) && matches(record.sessionId, query.sessionId) && matches(record.namespace, query.namespace) && matches(record.actor?.id, query.actor?.id);
27
- }
28
- function matches(left, right) {
29
- return right === void 0 || left === void 0 || left === right;
30
- }
31
- function score(content, terms) {
32
- const text = content.toLowerCase();
33
- return terms.reduce((total, term) => total + (text.includes(term) ? 1 : 0), 0);
34
- }
35
- //#endregion
1
+ import { readFile, readdir, realpath, stat } from "node:fs/promises";
2
+ import { dirname, isAbsolute, relative, resolve } from "node:path";
36
3
  //#region src/knowledge/knowledge.ts
4
+ function isProgressiveSkillProvider(provider) {
5
+ const candidate = provider;
6
+ return typeof candidate.load === "function" && typeof candidate.description === "string";
7
+ }
37
8
  function defineContextProvider(provider) {
38
9
  return provider;
39
10
  }
@@ -86,4 +57,233 @@ function stringifyKnowledge(value) {
86
57
  return typeof value === "string" ? value : JSON.stringify(value);
87
58
  }
88
59
  //#endregion
89
- export { InMemoryMemoryStore, createMemoryContextProvider, defineContextProvider, defineSkill };
60
+ //#region src/knowledge/agents-md.ts
61
+ const DEFAULT_MAX_BYTES$1 = 256 * 1024;
62
+ /**
63
+ * Reads one explicit `AGENTS.md` file as context.
64
+ *
65
+ * Fevex never walks the filesystem looking for `AGENTS.md`; register one
66
+ * provider per file and reference its name from `agent.context`.
67
+ */
68
+ function createAgentsMdContextProvider(options) {
69
+ const path = typeof options === "string" ? options : options.path;
70
+ const name = ((typeof options === "string" ? void 0 : options.name) ?? "agents-md").trim();
71
+ const maxBytes = (typeof options === "string" ? void 0 : options.maxBytes) ?? DEFAULT_MAX_BYTES$1;
72
+ if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) throw new TypeError("AGENTS.md maxBytes must be a positive safe integer");
73
+ if (!name.trim()) throw new TypeError("AGENTS.md provider name cannot be empty");
74
+ return defineContextProvider({
75
+ name,
76
+ async read() {
77
+ if ((await stat(path)).size > maxBytes) throw new Error(`AGENTS.md file "${path}" exceeds ${maxBytes} bytes`);
78
+ const content = await readFile(path, "utf8");
79
+ if (Buffer.byteLength(content) > maxBytes) throw new Error(`AGENTS.md file "${path}" exceeds ${maxBytes} bytes`);
80
+ return content.trim() ? [{
81
+ id: "agents-md",
82
+ content
83
+ }] : [];
84
+ }
85
+ });
86
+ }
87
+ //#endregion
88
+ //#region src/knowledge/in-memory-memory-store.ts
89
+ /** Volatile keyword-search memory store for tests and local development. */
90
+ var InMemoryMemoryStore = class {
91
+ #records = /* @__PURE__ */ new Map();
92
+ async search(query, context) {
93
+ context.signal?.throwIfAborted();
94
+ const terms = query.query.toLowerCase().split(/\s+/).filter(Boolean);
95
+ const scored = [...this.#records.values()].filter((record) => matchesScope(record, query)).map((record) => ({
96
+ record,
97
+ score: score(record.content, terms)
98
+ })).filter(({ score }) => !terms.length || score > 0).sort((left, right) => right.score - left.score || right.record.createdAt.localeCompare(left.record.createdAt));
99
+ return scored.slice(0, query.limit ?? scored.length).map(({ record }) => structuredClone(record));
100
+ }
101
+ async write(record, context) {
102
+ context.signal?.throwIfAborted();
103
+ const saved = {
104
+ id: crypto.randomUUID(),
105
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
106
+ ...structuredClone(record)
107
+ };
108
+ this.#records.set(saved.id, saved);
109
+ return structuredClone(saved);
110
+ }
111
+ };
112
+ function matchesScope(record, query) {
113
+ return matches(record.agentName, query.agentName) && matches(record.sessionId, query.sessionId) && matches(record.namespace, query.namespace) && matches(record.actor?.id, query.actor?.id);
114
+ }
115
+ function matches(left, right) {
116
+ return right === void 0 || left === void 0 || left === right;
117
+ }
118
+ function score(content, terms) {
119
+ const text = content.toLowerCase();
120
+ return terms.reduce((total, term) => total + (text.includes(term) ? 1 : 0), 0);
121
+ }
122
+ //#endregion
123
+ //#region src/knowledge/skill-file.ts
124
+ const DEFAULT_MAX_BYTES = 256 * 1024;
125
+ const DEFAULT_MAX_RESOURCE_BYTES = 256 * 1024;
126
+ const MAX_RESOURCES = 200;
127
+ const SKILL_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
128
+ const RESOURCE_DIRECTORIES = [
129
+ "references",
130
+ "scripts",
131
+ "assets"
132
+ ];
133
+ /**
134
+ * Loads one explicit `SKILL.md` file.
135
+ *
136
+ * Only `name` and `description` are advertised up front. The body and any
137
+ * files under `references/`, `scripts/` or `assets/` load on demand.
138
+ */
139
+ async function loadSkillFile(path, options = {}) {
140
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
141
+ const maxResourceBytes = options.maxResourceBytes ?? DEFAULT_MAX_RESOURCE_BYTES;
142
+ assertPositiveInteger(maxBytes, "maxBytes");
143
+ assertPositiveInteger(maxResourceBytes, "maxResourceBytes");
144
+ const absolute = await realpath(resolve(path));
145
+ if ((await stat(absolute)).size > maxBytes) throw new Error(`Skill file "${path}" exceeds ${maxBytes} bytes`);
146
+ const source = (await readFile(absolute, "utf8")).replace(/^\uFEFF/, "");
147
+ if (Buffer.byteLength(source) > maxBytes) throw new Error(`Skill file "${path}" exceeds ${maxBytes} bytes`);
148
+ const skill = parseSkillFile(source, path);
149
+ const root = dirname(absolute);
150
+ return defineContextProvider({
151
+ name: skill.name,
152
+ description: skill.description,
153
+ async read() {
154
+ return [{
155
+ id: `${skill.name}:metadata`,
156
+ content: skill.description
157
+ }];
158
+ },
159
+ async load(_context, resource) {
160
+ if (resource !== void 0) return [{
161
+ id: `${skill.name}:resource:${resource}`,
162
+ content: await readResource(root, resource, maxResourceBytes)
163
+ }];
164
+ const blocks = [{
165
+ id: `${skill.name}:instructions`,
166
+ content: skill.instructions
167
+ }];
168
+ const resources = await listResources(root);
169
+ if (resources.length) blocks.push({
170
+ id: `${skill.name}:resources`,
171
+ content: [
172
+ "Resources:",
173
+ ...resources.map((item) => `- ${item.path} (${formatBytes(item.size)})`),
174
+ "Load one by passing its path as the resource argument.",
175
+ ...resources.some((item) => item.path.startsWith("scripts/")) ? ["Scripts are for reference only and are not executed by this runtime."] : []
176
+ ].join("\n")
177
+ });
178
+ return blocks;
179
+ }
180
+ });
181
+ }
182
+ /** Loads several explicit `SKILL.md` files; it never scans directories. */
183
+ function loadSkillFiles(paths, options = {}) {
184
+ return Promise.all(paths.map((path) => loadSkillFile(path, options)));
185
+ }
186
+ function parseSkillFile(source, path) {
187
+ const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)([\s\S]*)$/.exec(source);
188
+ if (!match) throw new Error(`Skill file "${path}" must start with --- frontmatter`);
189
+ const fields = parseFrontmatter(match[1]);
190
+ const name = fields.name?.trim();
191
+ const description = fields.description?.trim();
192
+ const instructions = match[2].trim();
193
+ if (!name) throw new Error(`Skill file "${path}" must define a name`);
194
+ if (name.length > 64 || !SKILL_NAME.test(name) || name.startsWith("fevex__")) throw new Error(`Skill file "${path}" has an invalid name; use lowercase letters, numbers and hyphens, up to 64 characters`);
195
+ if (!description) throw new Error(`Skill file "${path}" must define a description`);
196
+ if (!instructions) throw new Error(`Skill file "${path}" must contain instructions`);
197
+ return {
198
+ name,
199
+ description,
200
+ instructions
201
+ };
202
+ }
203
+ function parseFrontmatter(source) {
204
+ const fields = {};
205
+ const lines = source.split(/\r?\n/);
206
+ for (let index = 0; index < lines.length; index += 1) {
207
+ const line = lines[index];
208
+ if (!line.trim() || line.trimStart().startsWith("#")) continue;
209
+ if (/^\s/.test(line)) continue;
210
+ const colon = line.indexOf(":");
211
+ if (colon <= 0) continue;
212
+ const key = line.slice(0, colon).trim();
213
+ let value = line.slice(colon + 1).trim();
214
+ if (value === "|" || value === ">" || value === "|-" || value === ">-") {
215
+ const block = [];
216
+ while (index + 1 < lines.length) {
217
+ const next = lines[index + 1];
218
+ if (next.trim() && !/^\s/.test(next)) break;
219
+ index += 1;
220
+ block.push(next.replace(/^\s+/, ""));
221
+ }
222
+ while (block.length && !block[block.length - 1]) block.pop();
223
+ value = value.startsWith(">") ? block.filter(Boolean).join(" ") : block.join("\n");
224
+ } else if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
225
+ fields[key] = value;
226
+ }
227
+ return fields;
228
+ }
229
+ async function listResources(root) {
230
+ const resources = [];
231
+ for (const directory of RESOURCE_DIRECTORIES) await walkResources(resolve(root, directory), root, resources);
232
+ return resources.sort((left, right) => left.path.localeCompare(right.path)).slice(0, MAX_RESOURCES);
233
+ }
234
+ async function walkResources(directory, root, resources) {
235
+ if (resources.length >= MAX_RESOURCES) return;
236
+ let entries;
237
+ try {
238
+ entries = await readdir(directory, { withFileTypes: true });
239
+ } catch (error) {
240
+ if (isMissing(error)) return;
241
+ throw error;
242
+ }
243
+ for (const entry of entries) {
244
+ if (resources.length >= MAX_RESOURCES) return;
245
+ if (entry.isSymbolicLink()) continue;
246
+ const target = resolve(directory, entry.name);
247
+ if (entry.isDirectory()) {
248
+ await walkResources(target, root, resources);
249
+ continue;
250
+ }
251
+ if (!entry.isFile()) continue;
252
+ const info = await stat(target);
253
+ resources.push({
254
+ path: relative(root, target).split("\\").join("/"),
255
+ size: info.size
256
+ });
257
+ }
258
+ }
259
+ async function readResource(root, resource, maxBytes) {
260
+ if (resource.includes("\0")) throw new Error("Skill resource path is invalid");
261
+ const requested = resolve(root, resource);
262
+ const requestedPath = relative(root, requested);
263
+ if (!requestedPath || requestedPath.startsWith("..") || isAbsolute(requestedPath)) throw new Error(`Skill resource "${resource}" is outside the skill directory`);
264
+ let target;
265
+ try {
266
+ target = await realpath(requested);
267
+ } catch {
268
+ throw new Error(`Skill resource "${resource}" was not found`);
269
+ }
270
+ const path = relative(root, target);
271
+ if (!path || path.startsWith("..") || isAbsolute(path)) throw new Error(`Skill resource "${resource}" is outside the skill directory`);
272
+ const info = await stat(target);
273
+ if (!info.isFile()) throw new Error(`Skill resource "${resource}" is not a file`);
274
+ if (info.size > maxBytes) throw new Error(`Skill resource "${resource}" exceeds ${maxBytes} bytes`);
275
+ const buffer = await readFile(target);
276
+ if (buffer.includes(0)) throw new Error(`Skill resource "${resource}" is not UTF-8 text`);
277
+ return buffer.toString("utf8");
278
+ }
279
+ function formatBytes(bytes) {
280
+ return bytes < 1024 ? `${bytes} B` : `${(bytes / 1024).toFixed(1)} KB`;
281
+ }
282
+ function assertPositiveInteger(value, name) {
283
+ if (!Number.isSafeInteger(value) || value <= 0) throw new TypeError(`Skill ${name} must be a positive safe integer`);
284
+ }
285
+ function isMissing(error) {
286
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
287
+ }
288
+ //#endregion
289
+ export { InMemoryMemoryStore, createAgentsMdContextProvider, createMemoryContextProvider, defineContextProvider, defineSkill, isProgressiveSkillProvider, loadSkillFile, loadSkillFiles };
@@ -1,9 +1,9 @@
1
1
  import { m as ToolCall } from "../types-B8laW1hM.mjs";
2
2
  import { a as ModelResult, n as ModelInput, t as ModelGateway } from "../index-BgKFd9yw.mjs";
3
3
  import { h as ElicitationRequest, p as DurableRunStore } from "../index-CzAi2Y_Z.mjs";
4
- import { s as MemoryStore } from "../index-BJktlD4E.mjs";
4
+ import { f as MemoryStore } from "../index-B0AdFbgr.mjs";
5
5
  import { d as ToolProvider } from "../index-5p3q2yIp.mjs";
6
- import { d as ChannelMessage, f as ChannelOutput, o as ChannelElicitationContext, r as ChannelAdapter } from "../index-DVw0zOc_.mjs";
6
+ import { d as ChannelMessage, f as ChannelOutput, o as ChannelElicitationContext, r as ChannelAdapter } from "../index-BTD1c4Ys.mjs";
7
7
  //#region src/testing/contracts.d.ts
8
8
  interface ModelGatewayContract {
9
9
  output?: unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fevex/core",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.7",
4
4
  "description": "Agent Engineering Framework for code-first, provider-neutral AI agents.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -1,70 +0,0 @@
1
- import { l as JsonValue, o as ExecutionContext, s as JsonObject } from "./types-B8laW1hM.mjs";
2
- import { L as SessionId } from "./index-CzAi2Y_Z.mjs";
3
- //#region src/knowledge/knowledge.d.ts
4
- /** Runtime context supplied to knowledge providers and memory stores. */
5
- interface KnowledgeContext {
6
- agentName: string;
7
- input: string;
8
- sessionId: SessionId;
9
- context?: ExecutionContext;
10
- signal?: AbortSignal;
11
- }
12
- interface ContextBlock {
13
- id: string;
14
- content: string;
15
- metadata?: JsonObject;
16
- }
17
- interface ContextProvider {
18
- name: string;
19
- read(context: KnowledgeContext): Promise<ContextBlock[]>;
20
- }
21
- interface MemoryQuery {
22
- query: string;
23
- limit?: number;
24
- agentName?: string;
25
- sessionId?: SessionId;
26
- namespace?: string;
27
- actor?: ExecutionContext['actor'];
28
- }
29
- interface MemoryWrite {
30
- content: string;
31
- agentName?: string;
32
- sessionId?: SessionId;
33
- namespace?: string;
34
- actor?: ExecutionContext['actor'];
35
- metadata?: JsonObject;
36
- }
37
- interface MemoryRecord extends MemoryWrite {
38
- id: string;
39
- createdAt: string;
40
- }
41
- interface MemoryStore {
42
- search(query: MemoryQuery, context: KnowledgeContext): Promise<MemoryRecord[]>;
43
- write(record: MemoryWrite, context: KnowledgeContext): Promise<MemoryRecord>;
44
- }
45
- interface SkillDefinition {
46
- name: string;
47
- instructions: string;
48
- resources?: Array<string | JsonValue | {
49
- id?: string;
50
- content: string | JsonValue;
51
- metadata?: JsonObject;
52
- }>;
53
- }
54
- declare function defineContextProvider<T extends ContextProvider>(provider: T): T;
55
- declare function defineSkill(skill: SkillDefinition): ContextProvider;
56
- declare function createMemoryContextProvider(options: {
57
- name?: string;
58
- store: MemoryStore;
59
- limit?: number;
60
- }): ContextProvider;
61
- //#endregion
62
- //#region src/knowledge/in-memory-memory-store.d.ts
63
- /** Volatile keyword-search memory store for tests and local development. */
64
- declare class InMemoryMemoryStore implements MemoryStore {
65
- #private;
66
- search(query: MemoryQuery, context: KnowledgeContext): Promise<MemoryRecord[]>;
67
- write(record: MemoryWrite, context: KnowledgeContext): Promise<MemoryRecord>;
68
- }
69
- //#endregion
70
- export { MemoryQuery as a, MemoryWrite as c, defineContextProvider as d, defineSkill as f, KnowledgeContext as i, SkillDefinition as l, ContextBlock as n, MemoryRecord as o, ContextProvider as r, MemoryStore as s, InMemoryMemoryStore as t, createMemoryContextProvider as u };