@nylorun/harness 0.7.0-beta.1 → 0.8.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +7 -2
- package/dist/build/agent.d.ts +2 -0
- package/dist/build/agent.js +4 -0
- package/dist/build/assemble.d.ts +4 -1
- package/dist/build/assemble.js +12 -2
- package/dist/build/builder.d.ts +28 -10
- package/dist/build/builder.js +59 -29
- package/dist/build/manifest.d.ts +2 -0
- package/dist/build/manifest.js +2 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/types/manifest.d.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@ All notable changes to `@nylorun/harness` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The project follows [Semantic Versioning](https://semver.org/). Before 1.0, the public API is experimental: breaking changes may occur in minor releases, while patch releases are reserved for compatible fixes.
|
|
6
6
|
|
|
7
|
+
## [0.8.0-beta.1] - 2026-08-31
|
|
8
|
+
|
|
9
|
+
### Breaking changes
|
|
10
|
+
|
|
11
|
+
- `Agent()` now takes identity options instead of a model adapter. Migrate
|
|
12
|
+
`Agent(adapter).use(...).build()` to
|
|
13
|
+
`Agent({ id, name, instructions }).use(...).with(adapter).build()`.
|
|
14
|
+
- `.build()` exists only on `BoundAgentBuilder`, the type returned by a single `.with(onModelCall)`.
|
|
15
|
+
`AgentBuilder` has `.use()` and `.with()` only.
|
|
16
|
+
- `AgentManifest` now includes `id` and `name`. Built agents expose the same fields as `agent.id`
|
|
17
|
+
and `agent.name`.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Optional constructor `instructions` compile as reserved `agent` middleware. A string is
|
|
22
|
+
normalized to one instruction. Capability-specific instructions still go through `.use()`.
|
|
23
|
+
|
|
7
24
|
## [0.7.0-beta.1] - 2026-08-30
|
|
8
25
|
|
|
9
26
|
### Breaking changes
|
|
@@ -75,3 +92,4 @@ The project follows [Semantic Versioning](https://semver.org/). Before 1.0, the
|
|
|
75
92
|
[0.5.0-beta.1]: https://github.com/nylorun/harness/tree/main/harness
|
|
76
93
|
[0.6.0-beta.1]: https://github.com/nylorun/harness/tree/main/harness
|
|
77
94
|
[0.7.0-beta.1]: https://github.com/nylorun/harness/tree/main/harness
|
|
95
|
+
[0.8.0-beta.1]: https://github.com/nylorun/harness/tree/main/harness
|
package/README.md
CHANGED
|
@@ -18,8 +18,13 @@ const echo = tool({
|
|
|
18
18
|
execute: async ({ text }) => ({ kind: "completed", output: text }),
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
const agent = Agent(
|
|
22
|
-
|
|
21
|
+
const agent = Agent({
|
|
22
|
+
id: "echo",
|
|
23
|
+
name: "Echo",
|
|
24
|
+
instructions: "Use echo when asked.",
|
|
25
|
+
})
|
|
26
|
+
.use({ id: "echo", tools: [echo] })
|
|
27
|
+
.with(adapter)
|
|
23
28
|
.build();
|
|
24
29
|
|
|
25
30
|
const result = await agent.run().input("Echo hello").completed;
|
package/dist/build/agent.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export declare class BuiltAgent {
|
|
|
10
10
|
#private;
|
|
11
11
|
readonly middleware: readonly BoundMiddleware[];
|
|
12
12
|
readonly manifest: AgentManifest;
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly name: string;
|
|
13
15
|
private constructor();
|
|
14
16
|
run(options?: SessionRunOptions): Session;
|
|
15
17
|
}
|
package/dist/build/agent.js
CHANGED
|
@@ -5,10 +5,14 @@ let createBoundAgent;
|
|
|
5
5
|
export class BuiltAgent {
|
|
6
6
|
middleware;
|
|
7
7
|
manifest;
|
|
8
|
+
id;
|
|
9
|
+
name;
|
|
8
10
|
#loopAgent;
|
|
9
11
|
constructor(middleware, invoke, manifest) {
|
|
10
12
|
this.middleware = middleware;
|
|
11
13
|
this.manifest = manifest;
|
|
14
|
+
this.id = manifest.id;
|
|
15
|
+
this.name = manifest.name;
|
|
12
16
|
this.#loopAgent = Object.freeze({
|
|
13
17
|
middleware,
|
|
14
18
|
invoke,
|
package/dist/build/assemble.d.ts
CHANGED
|
@@ -2,4 +2,7 @@ import type { BuildResult } from "../types/manifest.js";
|
|
|
2
2
|
import type { BoundMiddleware } from "../types/middleware.js";
|
|
3
3
|
import type { ModelAdapter } from "../types/model.js";
|
|
4
4
|
import { type BuiltAgent } from "./agent.js";
|
|
5
|
-
export declare function assembleAgent(middleware: readonly BoundMiddleware[], invoke: ModelAdapter
|
|
5
|
+
export declare function assembleAgent(middleware: readonly BoundMiddleware[], invoke: ModelAdapter, identity: Readonly<{
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
}>): BuildResult<BuiltAgent>;
|
package/dist/build/assemble.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { bindAgent } from "./agent.js";
|
|
2
2
|
import { createManifest } from "./manifest.js";
|
|
3
3
|
const diagnostic = (code, message, extra = {}) => Object.freeze({ code, message, ...extra });
|
|
4
|
-
export function assembleAgent(middleware, invoke) {
|
|
4
|
+
export function assembleAgent(middleware, invoke, identity) {
|
|
5
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
|
+
}
|
|
6
12
|
if (typeof invoke !== "function") {
|
|
7
13
|
diagnostics.push(diagnostic("harness.invalid-model", "A model invoke function is required"));
|
|
8
14
|
}
|
|
@@ -27,7 +33,11 @@ export function assembleAgent(middleware, invoke) {
|
|
|
27
33
|
if (diagnostics.length)
|
|
28
34
|
return Object.freeze({ ok: false, diagnostics: Object.freeze(diagnostics) });
|
|
29
35
|
const frozenMiddleware = Object.freeze(frozen);
|
|
30
|
-
const manifest = createManifest({
|
|
36
|
+
const manifest = createManifest({
|
|
37
|
+
id: identity.id,
|
|
38
|
+
name: identity.name,
|
|
39
|
+
middleware: frozenMiddleware,
|
|
40
|
+
});
|
|
31
41
|
const agent = bindAgent(frozenMiddleware, invoke, manifest);
|
|
32
42
|
return Object.freeze({ ok: true, agent, manifest });
|
|
33
43
|
}
|
package/dist/build/builder.d.ts
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
|
-
import type { CapabilityDeclaration, StepMiddleware } from "../types/middleware.js";
|
|
1
|
+
import type { BoundMiddleware, CapabilityDeclaration, StepMiddleware } from "../types/middleware.js";
|
|
2
2
|
import type { ModelAdapter } from "../types/model.js";
|
|
3
3
|
import type { BuildDiagnostic } from "../types/shared.js";
|
|
4
4
|
import { HarnessError } from "../errors.js";
|
|
5
5
|
import type { BuiltAgent } from "./agent.js";
|
|
6
|
+
export interface AgentOptions {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly instructions?: string | readonly string[];
|
|
10
|
+
}
|
|
11
|
+
interface BuilderState {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly middleware: BoundMiddleware[];
|
|
15
|
+
invoke?: ModelAdapter;
|
|
16
|
+
bound: boolean;
|
|
17
|
+
sealed: boolean;
|
|
18
|
+
agent?: BuiltAgent;
|
|
19
|
+
error?: AgentBuildError;
|
|
20
|
+
middlewareSeq: number;
|
|
21
|
+
}
|
|
6
22
|
export declare class AgentBuildError extends HarnessError {
|
|
7
23
|
readonly diagnostics: readonly BuildDiagnostic[];
|
|
8
24
|
constructor(diagnostics: readonly BuildDiagnostic[]);
|
|
@@ -10,19 +26,21 @@ export declare class AgentBuildError extends HarnessError {
|
|
|
10
26
|
export declare class AgentLifecycleError extends HarnessError {
|
|
11
27
|
constructor(message: string);
|
|
12
28
|
}
|
|
13
|
-
export declare function Agent(
|
|
29
|
+
export declare function Agent(options: AgentOptions): AgentBuilder;
|
|
14
30
|
export declare class AgentBuilder {
|
|
15
|
-
private readonly
|
|
16
|
-
|
|
17
|
-
private sealed;
|
|
18
|
-
private agent?;
|
|
19
|
-
private error?;
|
|
20
|
-
private middlewareSeq;
|
|
21
|
-
constructor(invoke: ModelAdapter);
|
|
31
|
+
private readonly state;
|
|
32
|
+
constructor(state: BuilderState);
|
|
22
33
|
use(middleware: StepMiddleware): this;
|
|
23
34
|
use(id: string, middleware: StepMiddleware): this;
|
|
24
35
|
use<State>(declaration: CapabilityDeclaration<State>): this;
|
|
25
|
-
|
|
36
|
+
with(onModelCall: ModelAdapter): BoundAgentBuilder;
|
|
26
37
|
private nextMiddlewareId;
|
|
27
38
|
private push;
|
|
39
|
+
private assertOpen;
|
|
40
|
+
}
|
|
41
|
+
export declare class BoundAgentBuilder {
|
|
42
|
+
private readonly state;
|
|
43
|
+
constructor(state: BuilderState);
|
|
44
|
+
build(): BuiltAgent;
|
|
28
45
|
}
|
|
46
|
+
export {};
|
package/dist/build/builder.js
CHANGED
|
@@ -14,18 +14,13 @@ export class AgentLifecycleError extends HarnessError {
|
|
|
14
14
|
this.name = "AgentLifecycleError";
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
export function Agent(
|
|
18
|
-
return new AgentBuilder(
|
|
17
|
+
export function Agent(options) {
|
|
18
|
+
return new AgentBuilder(createState(options));
|
|
19
19
|
}
|
|
20
20
|
export class AgentBuilder {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
agent;
|
|
25
|
-
error;
|
|
26
|
-
middlewareSeq = 0;
|
|
27
|
-
constructor(invoke) {
|
|
28
|
-
this.invoke = invoke;
|
|
21
|
+
state;
|
|
22
|
+
constructor(state) {
|
|
23
|
+
this.state = state;
|
|
29
24
|
}
|
|
30
25
|
use(idOrMiddleware, middleware) {
|
|
31
26
|
if (typeof idOrMiddleware === "function") {
|
|
@@ -35,35 +30,70 @@ export class AgentBuilder {
|
|
|
35
30
|
return this.push(compileDeclaration(idOrMiddleware));
|
|
36
31
|
return this.push({ id: idOrMiddleware, handle: middleware });
|
|
37
32
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this.sealed = true;
|
|
44
|
-
const result = assembleAgent(this.middleware, this.invoke);
|
|
45
|
-
if (!result.ok) {
|
|
46
|
-
this.error = new AgentBuildError(result.diagnostics);
|
|
47
|
-
throw this.error;
|
|
48
|
-
}
|
|
49
|
-
this.agent = result.agent;
|
|
50
|
-
return this.agent;
|
|
33
|
+
with(onModelCall) {
|
|
34
|
+
this.assertOpen("with()");
|
|
35
|
+
this.state.bound = true;
|
|
36
|
+
this.state.invoke = onModelCall;
|
|
37
|
+
return new BoundAgentBuilder(this.state);
|
|
51
38
|
}
|
|
52
39
|
nextMiddlewareId() {
|
|
53
|
-
const taken = new Set(this.middleware.map((item) => item.id));
|
|
40
|
+
const taken = new Set(this.state.middleware.map((item) => item.id));
|
|
54
41
|
let id;
|
|
55
42
|
do {
|
|
56
|
-
this.middlewareSeq += 1;
|
|
57
|
-
id = `middleware-${this.middlewareSeq}`;
|
|
43
|
+
this.state.middlewareSeq += 1;
|
|
44
|
+
id = `middleware-${this.state.middlewareSeq}`;
|
|
58
45
|
} while (taken.has(id));
|
|
59
46
|
return id;
|
|
60
47
|
}
|
|
61
48
|
push(entry) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.middleware.push(entry);
|
|
49
|
+
this.assertOpen("build()");
|
|
50
|
+
this.state.middleware.push(entry);
|
|
65
51
|
return this;
|
|
66
52
|
}
|
|
53
|
+
assertOpen(after) {
|
|
54
|
+
if (this.state.bound)
|
|
55
|
+
throw new AgentLifecycleError("AgentBuilder cannot be changed after with()");
|
|
56
|
+
if (this.state.sealed)
|
|
57
|
+
throw new AgentLifecycleError(`AgentBuilder cannot be changed after ${after}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export class BoundAgentBuilder {
|
|
61
|
+
state;
|
|
62
|
+
constructor(state) {
|
|
63
|
+
this.state = state;
|
|
64
|
+
}
|
|
65
|
+
build() {
|
|
66
|
+
if (this.state.agent)
|
|
67
|
+
return this.state.agent;
|
|
68
|
+
if (this.state.error)
|
|
69
|
+
throw this.state.error;
|
|
70
|
+
this.state.sealed = true;
|
|
71
|
+
const result = assembleAgent(this.state.middleware, this.state.invoke, {
|
|
72
|
+
id: this.state.id,
|
|
73
|
+
name: this.state.name,
|
|
74
|
+
});
|
|
75
|
+
if (!result.ok) {
|
|
76
|
+
this.state.error = new AgentBuildError(result.diagnostics);
|
|
77
|
+
throw this.state.error;
|
|
78
|
+
}
|
|
79
|
+
this.state.agent = result.agent;
|
|
80
|
+
return this.state.agent;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function createState(options) {
|
|
84
|
+
const middleware = [];
|
|
85
|
+
if (options.instructions !== undefined) {
|
|
86
|
+
const instructions = typeof options.instructions === "string" ? [options.instructions] : options.instructions;
|
|
87
|
+
middleware.push(compileDeclaration({ id: "agent", instructions }));
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
id: options.id,
|
|
91
|
+
name: options.name,
|
|
92
|
+
middleware,
|
|
93
|
+
bound: false,
|
|
94
|
+
sealed: false,
|
|
95
|
+
middlewareSeq: 0,
|
|
96
|
+
};
|
|
67
97
|
}
|
|
68
98
|
function compileDeclaration(declaration) {
|
|
69
99
|
const tools = copyItems(declaration.tools, declaration.id);
|
package/dist/build/manifest.d.ts
CHANGED
package/dist/build/manifest.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { Agent, AgentBuilder, AgentBuildError, AgentLifecycleError } from "./build/builder.js";
|
|
1
|
+
export { Agent, AgentBuilder, AgentBuildError, AgentLifecycleError, BoundAgentBuilder, } from "./build/builder.js";
|
|
2
|
+
export type { AgentOptions } from "./build/builder.js";
|
|
2
3
|
export { HarnessError, isHarnessError } from "./errors.js";
|
|
3
4
|
export type { HarnessErrorCode, HarnessErrorDetails, HarnessErrorOptions } from "./errors.js";
|
|
4
5
|
export { BuiltAgent } from "./build/agent.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Agent, AgentBuilder, AgentBuildError, AgentLifecycleError } from "./build/builder.js";
|
|
1
|
+
export { Agent, AgentBuilder, AgentBuildError, AgentLifecycleError, BoundAgentBuilder, } from "./build/builder.js";
|
|
2
2
|
export { HarnessError, isHarnessError } from "./errors.js";
|
|
3
3
|
export { BuiltAgent } from "./build/agent.js";
|
|
4
4
|
export { middleware, model, tool } from "./build/helpers.js";
|
package/dist/types/manifest.d.ts
CHANGED