@nylorun/core 0.0.0-bootstrap → 0.1.1-beta

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 (70) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +192 -0
  3. package/README.md +16 -0
  4. package/dist/compatibility.d.ts +3 -0
  5. package/dist/compatibility.js +3 -0
  6. package/dist/contracts.d.ts +246 -0
  7. package/dist/contracts.js +204 -0
  8. package/dist/define.d.ts +31 -0
  9. package/dist/define.js +15 -0
  10. package/dist/definition/assemble.d.ts +26 -0
  11. package/dist/definition/assemble.js +50 -0
  12. package/dist/definition/bind-agent.d.ts +8 -0
  13. package/dist/definition/bind-agent.js +61 -0
  14. package/dist/definition/bind-tool.d.ts +4 -0
  15. package/dist/definition/bind-tool.js +25 -0
  16. package/dist/definition/binding.d.ts +15 -0
  17. package/dist/definition/binding.js +9 -0
  18. package/dist/definition/bound.d.ts +20 -0
  19. package/dist/definition/bound.js +1 -0
  20. package/dist/definition/builder.d.ts +63 -0
  21. package/dist/definition/builder.js +215 -0
  22. package/dist/definition/declaration.d.ts +10 -0
  23. package/dist/definition/declaration.js +70 -0
  24. package/dist/definition/from.d.ts +6 -0
  25. package/dist/definition/from.js +135 -0
  26. package/dist/definition/helpers.d.ts +21 -0
  27. package/dist/definition/helpers.js +29 -0
  28. package/dist/definition/implementations.d.ts +16 -0
  29. package/dist/definition/implementations.js +3 -0
  30. package/dist/definition/manifest.d.ts +9 -0
  31. package/dist/definition/manifest.js +57 -0
  32. package/dist/definition/output-contract.d.ts +6 -0
  33. package/dist/definition/output-contract.js +12 -0
  34. package/dist/definition/schema-json.d.ts +3 -0
  35. package/dist/definition/schema-json.js +22 -0
  36. package/dist/definition/schema.d.ts +16 -0
  37. package/dist/definition/schema.js +281 -0
  38. package/dist/definition/tool-error.d.ts +9 -0
  39. package/dist/definition/tool-error.js +20 -0
  40. package/dist/errors.d.ts +17 -0
  41. package/dist/errors.js +22 -0
  42. package/dist/index.d.ts +10 -0
  43. package/dist/index.js +1 -0
  44. package/dist/types/agent.d.ts +12 -0
  45. package/dist/types/agent.js +1 -0
  46. package/dist/types/dynamics.d.ts +53 -0
  47. package/dist/types/dynamics.js +1 -0
  48. package/dist/types/manifest.d.ts +34 -0
  49. package/dist/types/manifest.js +1 -0
  50. package/dist/types/middleware.d.ts +74 -0
  51. package/dist/types/middleware.js +1 -0
  52. package/dist/types/model.d.ts +184 -0
  53. package/dist/types/model.js +1 -0
  54. package/dist/types/observe.d.ts +180 -0
  55. package/dist/types/observe.js +1 -0
  56. package/dist/types/shared.d.ts +25 -0
  57. package/dist/types/shared.js +1 -0
  58. package/dist/types/tool.d.ts +187 -0
  59. package/dist/types/tool.js +1 -0
  60. package/dist/types/transcript.d.ts +65 -0
  61. package/dist/types/transcript.js +1 -0
  62. package/dist/utils/canonical.d.ts +1 -0
  63. package/dist/utils/canonical.js +10 -0
  64. package/dist/utils/hash.d.ts +3 -0
  65. package/dist/utils/hash.js +7 -0
  66. package/dist/utils/immutable.d.ts +6 -0
  67. package/dist/utils/immutable.js +76 -0
  68. package/package.json +57 -7
  69. package/index.js +0 -1
  70. package/publish.out +0 -0
@@ -0,0 +1,31 @@
1
+ export { Agent, AgentBuilder, AgentBuildError, AgentLifecycleError, } from "./definition/builder.js";
2
+ export type { AgentOptions } from "./definition/builder.js";
3
+ export { HarnessError, isHarnessError } from "./errors.js";
4
+ export type { HarnessErrorCode, HarnessErrorDetails, HarnessErrorOptions, } from "./errors.js";
5
+ export type { BuiltAgent } from "./types/agent.js";
6
+ export { capability, middleware, model, tool } from "./definition/helpers.js";
7
+ export { ToolError, isToolError } from "./definition/tool-error.js";
8
+ export { defineSchema } from "./definition/schema.js";
9
+ export { hashManifest } from "./utils/hash.js";
10
+ export type { Implementations } from "./definition/implementations.js";
11
+ export type { AgentManifest, CapabilityManifest, ManifestTool, ManifestSchemaVersion, } from "./types/manifest.js";
12
+ export type { CapabilityDeclaration, CapabilityItems, MiddlewareContributions, StepMiddleware, StepRequest, StepResponse, } from "./types/middleware.js";
13
+ export type { Patch, Decision, BeforeModelCallFn, AfterModelCallFn, } from "./types/dynamics.js";
14
+ export type { ModelCandidate, ModelControls, ModelDirective, ModelEvidence, ModelFinishReason, ModelAdapter, ModelAdapterContext, ModelPreparedCall, ContextContributor, ContextMutationOptions, ContextSnapshot, ModelCall, ModelCallTool, ModelOutputBlock, PromptContentPart, PromptItem, ModelConfigurationContributor, ModelConfigurationInstruction, ModelConfigurationMutationOptions, ModelConfigurationSnapshot, ModelConfigurationTool, ModelRequest, ModelToolCall, ModelUsage, } from "./types/model.js";
15
+ export type { BuildDiagnostic, ContextItem, DeferredOutcome, JsonObject, JsonPrimitive, JsonValue, Tripwire, } from "./types/shared.js";
16
+ export type { ObserveEvent, ObserveModelConfigurationSnapshot, ObserveModelRequested, ObserveSealedCall, ObserveToolSnapshot, Observer, } from "./types/observe.js";
17
+ export type { InputEvent, MessageInput, InteractionReply, TranscriptEntry, UserContentPart, } from "./types/transcript.js";
18
+ export type { Interaction, RequiredInteraction, ToolContent, ToolDefinition, ToolDescriptor, ToolExecutionContext, ToolExecutionResume, ToolInputSchema, ToolOutputSchema, ToolSchema, ToolSchemaSource, StandardToolSchema, StandardSchemaIssue, SchemaIssue, SchemaValidation, SchemaOutput, ToolOwner, ToolOutcome, ToolResult, ToolValidationFailureDetails, ToolEffects, ToolApproval, ToolRunResult, SessionStateBag, } from "./types/tool.js";
19
+ export { normalizeToolDefinition, normalizedSchemasFor, } from "./definition/schema.js";
20
+ export { implementationsFor, bindingFromAgent } from "./definition/binding.js";
21
+ export type { AgentBinding } from "./definition/binding.js";
22
+ export type { BoundMiddleware, BoundToolDefinition, } from "./definition/bound.js";
23
+ export { bindTool } from "./definition/bind-tool.js";
24
+ export { bindOutputContract } from "./definition/output-contract.js";
25
+ export type { TurnOutputContract } from "./definition/output-contract.js";
26
+ export { agentFrom } from "./definition/from.js";
27
+ export { schemaFromJSON } from "./definition/schema-json.js";
28
+ export { normalizeSchema } from "./definition/schema.js";
29
+ export * from "./utils/immutable.js";
30
+ export * from "./utils/canonical.js";
31
+ export type { TranscriptToolsEntry } from "./types/transcript.js";
package/dist/define.js ADDED
@@ -0,0 +1,15 @@
1
+ export { Agent, AgentBuilder, AgentBuildError, AgentLifecycleError, } from "./definition/builder.js";
2
+ export { HarnessError, isHarnessError } from "./errors.js";
3
+ export { capability, middleware, model, tool } from "./definition/helpers.js";
4
+ export { ToolError, isToolError } from "./definition/tool-error.js";
5
+ export { defineSchema } from "./definition/schema.js";
6
+ export { hashManifest } from "./utils/hash.js";
7
+ export { normalizeToolDefinition, normalizedSchemasFor, } from "./definition/schema.js";
8
+ export { implementationsFor, bindingFromAgent } from "./definition/binding.js";
9
+ export { bindTool } from "./definition/bind-tool.js";
10
+ export { bindOutputContract } from "./definition/output-contract.js";
11
+ export { agentFrom } from "./definition/from.js";
12
+ export { schemaFromJSON } from "./definition/schema-json.js";
13
+ export { normalizeSchema } from "./definition/schema.js";
14
+ export * from "./utils/immutable.js";
15
+ export * from "./utils/canonical.js";
@@ -0,0 +1,26 @@
1
+ import type { BoundMiddleware } from "./bound.js";
2
+ import type { BuiltAgent } from "../types/agent.js";
3
+ import type { AgentManifest } from "../types/manifest.js";
4
+ import type { BuildDiagnostic } from "../types/shared.js";
5
+ import type { ToolSchemaSource } from "../types/tool.js";
6
+ import type { AfterModelCallFn, BeforeModelCallFn } from "../types/dynamics.js";
7
+ import type { StepMiddleware } from "../types/middleware.js";
8
+ type BuildResult<Agent> = {
9
+ readonly ok: true;
10
+ readonly agent: Agent;
11
+ readonly manifest: AgentManifest;
12
+ } | {
13
+ readonly ok: false;
14
+ readonly diagnostics: readonly BuildDiagnostic[];
15
+ };
16
+ export interface CapabilityDynamics {
17
+ readonly beforeModelCall?: BeforeModelCallFn<any>;
18
+ readonly afterModelCall?: AfterModelCallFn<any>;
19
+ readonly middleware?: StepMiddleware<any>;
20
+ }
21
+ export declare function assembleAgent(middleware: readonly BoundMiddleware[], identity: Readonly<{
22
+ id: string;
23
+ name: string;
24
+ outputSchema?: ToolSchemaSource;
25
+ }>, dynamics?: ReadonlyMap<string, CapabilityDynamics>): BuildResult<BuiltAgent>;
26
+ export {};
@@ -0,0 +1,50 @@
1
+ import { bindAgent } from "./bind-agent.js";
2
+ import { createManifest } from "./manifest.js";
3
+ const diagnostic = (code, message, extra = {}) => Object.freeze({ code, message, ...extra });
4
+ export function assembleAgent(middleware, identity, dynamics = new Map()) {
5
+ const diagnostics = [];
6
+ if (typeof identity.id !== "string" || identity.id.length === 0) {
7
+ diagnostics.push(diagnostic("agent.invalid-id", "Agent id must be a non-empty string"));
8
+ }
9
+ if (typeof identity.name !== "string" || identity.name.length === 0) {
10
+ diagnostics.push(diagnostic("agent.invalid-name", "Agent name must be a non-empty string"));
11
+ }
12
+ const middlewareIds = new Set();
13
+ const frozen = [];
14
+ for (const item of middleware) {
15
+ if (!item.id)
16
+ diagnostics.push(diagnostic("middleware.invalid-id", "Middleware id must not be empty"));
17
+ else if (middlewareIds.has(item.id))
18
+ diagnostics.push(diagnostic("middleware.duplicate-id", `Duplicate middleware id '${item.id}'`));
19
+ else if (typeof item.handle !== "function")
20
+ diagnostics.push(diagnostic("middleware.invalid", `Middleware '${item.id}' must provide a function`));
21
+ else {
22
+ middlewareIds.add(item.id);
23
+ frozen.push(Object.freeze({
24
+ id: item.id,
25
+ handle: item.handle,
26
+ hasMiddleware: item.hasMiddleware,
27
+ ...(item.tools === undefined ? {} : { tools: item.tools }),
28
+ ...(item.contributions === undefined
29
+ ? {}
30
+ : { contributions: item.contributions }),
31
+ ...(item.beforeModelCall ? { beforeModelCall: true } : {}),
32
+ ...(item.afterModelCall ? { afterModelCall: true } : {}),
33
+ }));
34
+ }
35
+ }
36
+ if (diagnostics.length)
37
+ return Object.freeze({
38
+ ok: false,
39
+ diagnostics: Object.freeze(diagnostics),
40
+ });
41
+ const frozenMiddleware = Object.freeze(frozen);
42
+ const manifest = createManifest({
43
+ id: identity.id,
44
+ name: identity.name,
45
+ outputSchema: identity.outputSchema,
46
+ middleware: frozenMiddleware,
47
+ });
48
+ const agent = bindAgent(frozenMiddleware, manifest, identity, dynamics);
49
+ return Object.freeze({ ok: true, agent, manifest });
50
+ }
@@ -0,0 +1,8 @@
1
+ import type { AgentManifest } from "../types/manifest.js";
2
+ import type { BoundMiddleware } from "./bound.js";
3
+ import type { BuiltAgent } from "../types/agent.js";
4
+ import type { ToolSchemaSource } from "../types/tool.js";
5
+ import type { CapabilityDynamics } from "./assemble.js";
6
+ export declare function bindAgent(middleware: readonly BoundMiddleware[], manifest: AgentManifest, options?: {
7
+ outputSchema?: ToolSchemaSource;
8
+ }, dynamics?: ReadonlyMap<string, CapabilityDynamics>): BuiltAgent;
@@ -0,0 +1,61 @@
1
+ import { bindTool } from "./bind-tool.js";
2
+ import { HarnessError } from "../errors.js";
3
+ import { bindOutputContract } from "./output-contract.js";
4
+ import { hashManifest } from "../utils/hash.js";
5
+ export function bindAgent(middleware, manifest, options = {}, dynamics = new Map()) {
6
+ const seen = new Set();
7
+ const keys = new Set();
8
+ const tools = [];
9
+ for (const declaration of middleware)
10
+ for (const tool of declaration.tools ?? []) {
11
+ const key = JSON.stringify([declaration.id, tool.name]);
12
+ if (seen.has(tool) || keys.has(key))
13
+ throw new HarnessError("tool.invalid", `Duplicate registered tool '${tool.name}' in '${declaration.id}'`);
14
+ seen.add(tool);
15
+ keys.add(key);
16
+ tools.push(bindTool(tool, { middlewareId: declaration.id, slot: declaration.id }));
17
+ }
18
+ const implementations = buildImplementations(middleware, dynamics, tools);
19
+ const binding = Object.freeze({
20
+ declarations: middleware,
21
+ tools: Object.freeze(tools),
22
+ ...(options.outputSchema === undefined
23
+ ? {}
24
+ : { outputSchema: options.outputSchema }),
25
+ manifest,
26
+ implementations,
27
+ });
28
+ // Validate the live output schema at authoring time without compiling engine state.
29
+ if (options.outputSchema)
30
+ bindOutputContract(options.outputSchema);
31
+ const agent = {
32
+ id: manifest.id,
33
+ name: manifest.name,
34
+ manifest,
35
+ hash: hashManifest(manifest),
36
+ toJSON: () => manifest,
37
+ };
38
+ Object.defineProperty(agent, "getBinding", {
39
+ value: () => binding,
40
+ enumerable: false,
41
+ });
42
+ return agent;
43
+ }
44
+ function buildImplementations(middleware, dynamics, snapshots) {
45
+ const table = {};
46
+ for (const item of middleware) {
47
+ const tools = {};
48
+ for (const tool of snapshots.filter((tool) => tool.owner.middlewareId === item.id))
49
+ tools[tool.name] = tool;
50
+ const dyn = dynamics.get(item.id);
51
+ table[item.id] = Object.freeze({
52
+ ...(Object.keys(tools).length
53
+ ? { tools: Object.freeze({ ...tools }) }
54
+ : {}),
55
+ ...(dyn?.beforeModelCall ? { beforeModelCall: dyn.beforeModelCall } : {}),
56
+ ...(dyn?.afterModelCall ? { afterModelCall: dyn.afterModelCall } : {}),
57
+ ...(dyn?.middleware ? { middleware: dyn.middleware } : {}),
58
+ });
59
+ }
60
+ return Object.freeze(table);
61
+ }
@@ -0,0 +1,4 @@
1
+ import type { BoundToolDefinition } from "./bound.js";
2
+ import type { ToolDefinition } from "../types/tool.js";
3
+ /** Prepares an executable Tool and records its middleware slot provenance. */
4
+ export declare function bindTool(item: ToolDefinition, owner: BoundToolDefinition["owner"]): BoundToolDefinition;
@@ -0,0 +1,25 @@
1
+ import { HarnessError } from "../errors.js";
2
+ import { normalizeToolDefinition, normalizedSchemasFor } from "./schema.js";
3
+ /** Prepares an executable Tool and records its middleware slot provenance. */
4
+ export function bindTool(item, owner) {
5
+ const prepared = normalizeToolDefinition(item);
6
+ if (!prepared.name)
7
+ throw new HarnessError("tool.invalid-name", "Tool name must not be empty");
8
+ if (typeof prepared.execute !== "function")
9
+ throw new HarnessError("tool.invalid", `Tool '${prepared.name}' must provide execute()`);
10
+ const schemas = normalizedSchemasFor(prepared);
11
+ return Object.freeze({
12
+ // Keep the original object identity so ToolRegistry WeakMap lookups succeed.
13
+ source: item,
14
+ name: prepared.name,
15
+ ...(prepared.description ? { description: prepared.description } : {}),
16
+ inputSchema: schemas.inputSchema,
17
+ ...(schemas.outputSchema === undefined
18
+ ? {}
19
+ : { outputSchema: schemas.outputSchema }),
20
+ execute: prepared.execute.bind(prepared),
21
+ ...(prepared.approval === undefined ? {} : { approval: prepared.approval }),
22
+ ...(prepared.effects === undefined ? {} : { effects: prepared.effects }),
23
+ owner: Object.freeze({ ...owner }),
24
+ });
25
+ }
@@ -0,0 +1,15 @@
1
+ import type { AgentManifest } from "../types/manifest.js";
2
+ import type { BuiltAgent } from "../types/agent.js";
3
+ import type { ToolSchemaSource } from "../types/tool.js";
4
+ import type { BoundMiddleware, BoundToolDefinition } from "./bound.js";
5
+ import type { Implementations } from "./implementations.js";
6
+ /** Local code binding. Only manifest is serializable; functions stay in the application. */
7
+ export interface AgentBinding {
8
+ readonly manifest: AgentManifest;
9
+ readonly tools: readonly BoundToolDefinition[];
10
+ readonly declarations: readonly BoundMiddleware[];
11
+ readonly implementations: Implementations;
12
+ readonly outputSchema?: ToolSchemaSource;
13
+ }
14
+ export declare function bindingFromAgent(agent: BuiltAgent): AgentBinding;
15
+ export declare function implementationsFor(agent: BuiltAgent): Implementations;
@@ -0,0 +1,9 @@
1
+ import { HarnessError } from "../errors.js";
2
+ export function bindingFromAgent(agent) {
3
+ if (!agent || typeof agent.getBinding !== "function")
4
+ throw new HarnessError("execution.invalid-input", "An agent with getBinding() is required");
5
+ return agent.getBinding();
6
+ }
7
+ export function implementationsFor(agent) {
8
+ return bindingFromAgent(agent).implementations;
9
+ }
@@ -0,0 +1,20 @@
1
+ import type { MiddlewareContributions, StepMiddleware } from "../types/middleware.js";
2
+ import type { ToolApproval, ToolDefinition, ToolEffects, ToolExecutionContext, ToolInputSchema, ToolOutputSchema, ToolOwner, ToolRunResult, ToolSchema } from "../types/tool.js";
3
+ export interface BoundToolDefinition<Info = unknown> extends Omit<ToolDefinition<ToolInputSchema, Info, ToolOutputSchema | undefined>, "inputSchema" | "outputSchema" | "execute" | "run" | "input" | "output"> {
4
+ readonly inputSchema: ToolSchema<unknown>;
5
+ readonly outputSchema?: ToolSchema<unknown>;
6
+ readonly execute: (args: unknown, context: ToolExecutionContext<Info>) => Promise<ToolRunResult>;
7
+ readonly approval?: ToolApproval<ToolInputSchema>;
8
+ readonly effects?: ToolEffects;
9
+ readonly owner: ToolOwner;
10
+ readonly source: ToolDefinition<any, any, any>;
11
+ }
12
+ export interface BoundMiddleware {
13
+ readonly id: string;
14
+ readonly handle: StepMiddleware;
15
+ readonly hasMiddleware: boolean;
16
+ readonly tools?: readonly ToolDefinition<any, any, any>[];
17
+ readonly contributions?: MiddlewareContributions;
18
+ readonly beforeModelCall?: boolean;
19
+ readonly afterModelCall?: boolean;
20
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,63 @@
1
+ import type { BoundMiddleware } from "./bound.js";
2
+ import type { CapabilityDeclaration, StepMiddleware } from "../types/middleware.js";
3
+ import type { BuildDiagnostic } from "../types/shared.js";
4
+ import { HarnessError } from "../errors.js";
5
+ import type { ToolDefinition, ToolSchemaSource, SchemaOutput } from "../types/tool.js";
6
+ import type { BuiltAgent } from "../types/agent.js";
7
+ import type { AgentManifest } from "../types/manifest.js";
8
+ import type { AfterModelCallFn, BeforeModelCallFn } from "../types/dynamics.js";
9
+ import type { Implementations } from "./implementations.js";
10
+ import { type CapabilityDynamics } from "./assemble.js";
11
+ export interface AgentOptions<Schema extends ToolSchemaSource | undefined = undefined> {
12
+ readonly outputSchema?: Schema;
13
+ readonly id: string;
14
+ readonly name: string;
15
+ readonly instructions?: string | readonly string[];
16
+ /** Top-level tools (H2). Composed as capability id `"agent"`. */
17
+ readonly tools?: readonly ToolDefinition<any, any, any>[];
18
+ }
19
+ interface BuilderSnapshot {
20
+ readonly id: string;
21
+ readonly name: string;
22
+ readonly outputSchema?: ToolSchemaSource;
23
+ readonly entries: readonly BoundMiddleware[];
24
+ readonly dynamics: ReadonlyMap<string, CapabilityDynamics>;
25
+ readonly agentBefore?: BeforeModelCallFn;
26
+ readonly agentAfter?: AfterModelCallFn;
27
+ }
28
+ export declare class AgentBuildError extends HarnessError {
29
+ readonly diagnostics: readonly BuildDiagnostic[];
30
+ constructor(diagnostics: readonly BuildDiagnostic[]);
31
+ }
32
+ export declare class AgentLifecycleError extends HarnessError {
33
+ constructor(message: string);
34
+ }
35
+ export declare function Agent<Info = unknown, Schema extends ToolSchemaSource | undefined = undefined>(options: AgentOptions<Schema>): AgentBuilder<Info, Schema>;
36
+ export declare namespace Agent {
37
+ function from<Info = unknown>(json: AgentManifest | import("../types/shared.js").JsonObject, implementations: Implementations<Info>): BuiltAgent<Info>;
38
+ }
39
+ declare const SNAPSHOT: unique symbol;
40
+ export declare class AgentBuilder<Info = unknown, Schema extends ToolSchemaSource | undefined = undefined> {
41
+ #private;
42
+ getBinding(): import("./binding.js").AgentBinding;
43
+ constructor(options: AgentOptions<Schema>);
44
+ /** @internal */
45
+ constructor(snapshot: BuilderSnapshot, brand: typeof SNAPSHOT);
46
+ static create<Info, Schema extends ToolSchemaSource | undefined>(options: AgentOptions<Schema>): AgentBuilder<Info, Schema>;
47
+ private static withSnapshot;
48
+ /** Compose-time identity — available before `.build()`. */
49
+ get id(): string;
50
+ get name(): string;
51
+ get manifest(): AgentManifest;
52
+ get hash(): string;
53
+ toJSON(): AgentManifest;
54
+ use(middleware: StepMiddleware<Info>): AgentBuilder<Info, Schema>;
55
+ use(id: string, middleware: StepMiddleware<Info>): AgentBuilder<Info, Schema>;
56
+ use(declaration: CapabilityDeclaration<Info>): AgentBuilder<Info, Schema>;
57
+ beforeModelCall(fn: BeforeModelCallFn<Info>): AgentBuilder<Info, Schema>;
58
+ afterModelCall(fn: AfterModelCallFn<Info>): AgentBuilder<Info, Schema>;
59
+ /** Optional no-op: returns the assembled agent facade. */
60
+ build(): BuiltAgent<Info, Schema extends ToolSchemaSource ? SchemaOutput<Schema> : string>;
61
+ private ensure;
62
+ }
63
+ export type { Implementations };
@@ -0,0 +1,215 @@
1
+ import { HarnessError } from "../errors.js";
2
+ import { assembleAgent } from "./assemble.js";
3
+ import { compileDeclaration } from "./declaration.js";
4
+ import { agentFrom } from "./from.js";
5
+ export class AgentBuildError extends HarnessError {
6
+ diagnostics;
7
+ constructor(diagnostics) {
8
+ super("agent.build-failed", diagnostics.map((item) => item.message).join("; ") || "Agent build failed");
9
+ this.diagnostics = diagnostics;
10
+ this.name = "AgentBuildError";
11
+ }
12
+ }
13
+ export class AgentLifecycleError extends HarnessError {
14
+ constructor(message) {
15
+ super("agent.lifecycle-sealed", message);
16
+ this.name = "AgentLifecycleError";
17
+ }
18
+ }
19
+ export function Agent(options) {
20
+ return AgentBuilder.create(options);
21
+ }
22
+ (function (Agent) {
23
+ function from(json, implementations) {
24
+ return agentFrom(json, implementations);
25
+ }
26
+ Agent.from = from;
27
+ })(Agent || (Agent = {}));
28
+ const SNAPSHOT = Symbol("AgentBuilder.snapshot");
29
+ export class AgentBuilder {
30
+ #snapshot;
31
+ #agent;
32
+ #error;
33
+ getBinding() {
34
+ return this.build().getBinding();
35
+ }
36
+ constructor(optionsOrSnapshot, brand) {
37
+ this.#snapshot =
38
+ brand === SNAPSHOT
39
+ ? optionsOrSnapshot
40
+ : createSnapshot(optionsOrSnapshot);
41
+ }
42
+ static create(options) {
43
+ return new AgentBuilder(options);
44
+ }
45
+ static withSnapshot(snapshot) {
46
+ return new AgentBuilder(snapshot, SNAPSHOT);
47
+ }
48
+ /** Compose-time identity — available before `.build()`. */
49
+ get id() {
50
+ return this.#snapshot.id;
51
+ }
52
+ get name() {
53
+ return this.#snapshot.name;
54
+ }
55
+ get manifest() {
56
+ return this.ensure().manifest;
57
+ }
58
+ get hash() {
59
+ return this.ensure().hash;
60
+ }
61
+ toJSON() {
62
+ return this.ensure().toJSON();
63
+ }
64
+ use(idOrMiddleware, middleware) {
65
+ let compiled;
66
+ if (typeof idOrMiddleware === "function") {
67
+ compiled = {
68
+ bound: {
69
+ id: nextMiddlewareId(this.#snapshot.entries),
70
+ handle: idOrMiddleware,
71
+ hasMiddleware: true,
72
+ },
73
+ middleware: idOrMiddleware,
74
+ };
75
+ }
76
+ else if (typeof idOrMiddleware === "object") {
77
+ compiled = compileDeclaration(idOrMiddleware);
78
+ }
79
+ else {
80
+ compiled = {
81
+ bound: {
82
+ id: idOrMiddleware,
83
+ handle: middleware,
84
+ hasMiddleware: true,
85
+ },
86
+ middleware: middleware,
87
+ };
88
+ }
89
+ const dynamics = new Map(this.#snapshot.dynamics);
90
+ dynamics.set(compiled.bound.id, {
91
+ ...(compiled.beforeModelCall
92
+ ? { beforeModelCall: compiled.beforeModelCall }
93
+ : {}),
94
+ ...(compiled.afterModelCall
95
+ ? { afterModelCall: compiled.afterModelCall }
96
+ : {}),
97
+ ...(compiled.middleware ? { middleware: compiled.middleware } : {}),
98
+ });
99
+ return AgentBuilder.withSnapshot({
100
+ ...this.#snapshot,
101
+ entries: Object.freeze([...this.#snapshot.entries, compiled.bound]),
102
+ dynamics,
103
+ });
104
+ }
105
+ beforeModelCall(fn) {
106
+ const dynamics = new Map(this.#snapshot.dynamics);
107
+ const existing = dynamics.get("agent") ?? {};
108
+ dynamics.set("agent", {
109
+ ...existing,
110
+ beforeModelCall: fn,
111
+ });
112
+ const entries = ensureAgentCapabilityFlag(this.#snapshot.entries, "beforeModelCall");
113
+ return AgentBuilder.withSnapshot({
114
+ ...this.#snapshot,
115
+ entries,
116
+ dynamics,
117
+ agentBefore: fn,
118
+ });
119
+ }
120
+ afterModelCall(fn) {
121
+ const dynamics = new Map(this.#snapshot.dynamics);
122
+ const existing = dynamics.get("agent") ?? {};
123
+ dynamics.set("agent", {
124
+ ...existing,
125
+ afterModelCall: fn,
126
+ });
127
+ const entries = ensureAgentCapabilityFlag(this.#snapshot.entries, "afterModelCall");
128
+ return AgentBuilder.withSnapshot({
129
+ ...this.#snapshot,
130
+ entries,
131
+ dynamics,
132
+ agentAfter: fn,
133
+ });
134
+ }
135
+ /** Optional no-op: returns the assembled agent facade. */
136
+ build() {
137
+ return this.ensure();
138
+ }
139
+ ensure() {
140
+ if (this.#agent)
141
+ return this.#agent;
142
+ if (this.#error)
143
+ throw this.#error;
144
+ const result = assembleAgent(this.#snapshot.entries, {
145
+ id: this.#snapshot.id,
146
+ name: this.#snapshot.name,
147
+ outputSchema: this.#snapshot.outputSchema,
148
+ }, this.#snapshot.dynamics);
149
+ if (!result.ok) {
150
+ this.#error = new AgentBuildError(result.diagnostics);
151
+ throw this.#error;
152
+ }
153
+ this.#agent = result.agent;
154
+ return this.#agent;
155
+ }
156
+ }
157
+ function createSnapshot(options) {
158
+ const entries = [];
159
+ const dynamics = new Map();
160
+ const instructions = options.instructions === undefined
161
+ ? undefined
162
+ : typeof options.instructions === "string"
163
+ ? [options.instructions]
164
+ : options.instructions;
165
+ if (instructions !== undefined || options.tools !== undefined) {
166
+ const compiled = compileDeclaration({
167
+ id: "agent",
168
+ ...(instructions === undefined ? {} : { instructions }),
169
+ ...(options.tools === undefined ? {} : { tools: options.tools }),
170
+ });
171
+ entries.push(compiled.bound);
172
+ dynamics.set("agent", {});
173
+ }
174
+ return {
175
+ id: options.id,
176
+ name: options.name,
177
+ outputSchema: options.outputSchema,
178
+ entries: Object.freeze(entries),
179
+ dynamics,
180
+ };
181
+ }
182
+ function nextMiddlewareId(entries) {
183
+ const taken = new Set(entries.map((item) => item.id));
184
+ let seq = 0;
185
+ let id;
186
+ do {
187
+ seq += 1;
188
+ id = `middleware-${seq}`;
189
+ } while (taken.has(id));
190
+ return id;
191
+ }
192
+ function ensureAgentCapabilityFlag(entries, flag) {
193
+ const index = entries.findIndex((item) => item.id === "agent");
194
+ if (index >= 0) {
195
+ const current = entries[index];
196
+ if (current[flag])
197
+ return entries;
198
+ const next = Object.freeze({ ...current, [flag]: true });
199
+ return Object.freeze([
200
+ ...entries.slice(0, index),
201
+ next,
202
+ ...entries.slice(index + 1),
203
+ ]);
204
+ }
205
+ return Object.freeze([
206
+ ...entries,
207
+ Object.freeze({
208
+ id: "agent",
209
+ handle: async (_request, next) => next(),
210
+ hasMiddleware: false,
211
+ contributions: Object.freeze({}),
212
+ [flag]: true,
213
+ }),
214
+ ]);
215
+ }
@@ -0,0 +1,10 @@
1
+ import type { BoundMiddleware } from "./bound.js";
2
+ import type { CapabilityDeclaration, StepMiddleware } from "../types/middleware.js";
3
+ import type { AfterModelCallFn, BeforeModelCallFn } from "../types/dynamics.js";
4
+ export interface CompiledCapability {
5
+ readonly bound: BoundMiddleware;
6
+ readonly beforeModelCall?: BeforeModelCallFn<any>;
7
+ readonly afterModelCall?: AfterModelCallFn<any>;
8
+ readonly middleware?: StepMiddleware<any>;
9
+ }
10
+ export declare function compileDeclaration<State>(declaration: CapabilityDeclaration<State>): CompiledCapability;
@@ -0,0 +1,70 @@
1
+ export function compileDeclaration(declaration) {
2
+ const tools = copyItems(declaration.tools, declaration.id);
3
+ const instructions = copyItems(declaration.instructions, declaration.id);
4
+ const model = declaration.model;
5
+ const contributions = snapshotContributions(instructions?.items, tools?.items, model);
6
+ const handle = async (request, next) => {
7
+ if (tools)
8
+ request.configuration.tools.set(tools.slot, tools.items);
9
+ if (instructions)
10
+ request.configuration.instructions.set(instructions.slot, instructions.items);
11
+ if (model)
12
+ request.configuration.model.select(model);
13
+ return declaration.middleware
14
+ ? declaration.middleware(request, next)
15
+ : next();
16
+ };
17
+ return {
18
+ bound: {
19
+ id: declaration.id,
20
+ handle,
21
+ hasMiddleware: declaration.middleware !== undefined,
22
+ tools: tools?.items,
23
+ ...(contributions === undefined ? {} : { contributions }),
24
+ ...(declaration.beforeModelCall ? { beforeModelCall: true } : {}),
25
+ ...(declaration.afterModelCall ? { afterModelCall: true } : {}),
26
+ },
27
+ ...(declaration.beforeModelCall
28
+ ? { beforeModelCall: declaration.beforeModelCall }
29
+ : {}),
30
+ ...(declaration.afterModelCall
31
+ ? { afterModelCall: declaration.afterModelCall }
32
+ : {}),
33
+ ...(declaration.middleware ? { middleware: declaration.middleware } : {}),
34
+ };
35
+ }
36
+ function snapshotContributions(instructions, tools, model) {
37
+ const snapInstructions = instructions === undefined ? undefined : Object.freeze([...instructions]);
38
+ const snapTools = tools === undefined
39
+ ? undefined
40
+ : Object.freeze(tools.map((tool) => Object.freeze({
41
+ name: tool.name,
42
+ ...(tool.description === undefined
43
+ ? {}
44
+ : { description: tool.description }),
45
+ })));
46
+ // Model is Runtime-owned for the published manifest; still allow local middleware select().
47
+ void model;
48
+ if (snapInstructions === undefined && snapTools === undefined) {
49
+ return undefined;
50
+ }
51
+ return Object.freeze({
52
+ ...(snapInstructions === undefined
53
+ ? {}
54
+ : { instructions: snapInstructions }),
55
+ ...(snapTools === undefined ? {} : { tools: snapTools }),
56
+ });
57
+ }
58
+ function copyItems(value, defaultSlot) {
59
+ if (value === undefined)
60
+ return undefined;
61
+ if (!("items" in value))
62
+ return Object.freeze({
63
+ slot: defaultSlot,
64
+ items: Object.freeze([...value]),
65
+ });
66
+ return Object.freeze({
67
+ slot: value.slot,
68
+ items: Object.freeze([...value.items]),
69
+ });
70
+ }
@@ -0,0 +1,6 @@
1
+ import type { AgentManifest } from "../types/manifest.js";
2
+ import type { BuiltAgent } from "../types/agent.js";
3
+ import type { JsonObject } from "../types/shared.js";
4
+ import type { Implementations } from "./implementations.js";
5
+ /** Rebuild an agent from manifest JSON + in-process implementations (T28). */
6
+ export declare function agentFrom<Info = unknown>(json: AgentManifest | JsonObject, implementations: Implementations<Info>): BuiltAgent<Info>;