@axiastudio/aioc 0.2.0-next.2 → 0.2.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/README.md +21 -3
- package/dist/approval-helpers.d.ts +24 -0
- package/dist/approval-helpers.d.ts.map +1 -0
- package/dist/approval-helpers.js +94 -0
- package/dist/harness-descriptor-loader-paths.d.ts +29 -0
- package/dist/harness-descriptor-loader-paths.d.ts.map +1 -0
- package/dist/harness-descriptor-loader-paths.js +124 -0
- package/dist/harness-descriptor-loader.d.ts +13 -0
- package/dist/harness-descriptor-loader.d.ts.map +1 -0
- package/dist/harness-descriptor-loader.js +158 -0
- package/dist/harness-descriptor.d.ts.map +1 -1
- package/dist/harness-descriptor.js +12 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,12 +8,18 @@ Project home and documentation: [https://axiastudio.github.io/aioc](https://axia
|
|
|
8
8
|
|
|
9
9
|
## Release Status
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Current stable release: `0.2.1`.
|
|
12
|
+
The stable line started with `0.1.0`.
|
|
12
13
|
The core runtime surface is compatibility-managed. Breaking changes to the stable surface should ship only with explicit migration guidance and release notes.
|
|
13
14
|
|
|
14
15
|
### Stable Scope
|
|
15
16
|
|
|
16
|
-
AIOC `0.1.0`
|
|
17
|
+
AIOC `0.1.0` stabilized the core runtime surface, public documentation aligned to the exported contract, `RunRecord` and replay/compare workflows, and the governance-first runtime model validated in real applications beyond toy examples.
|
|
18
|
+
AIOC `0.1.1` adds thread-history utilities, the run-output stream adapter, and provider-specific instruction-role documentation without changing the stable governance model.
|
|
19
|
+
AIOC `0.1.2` adds approval evidence helpers for application-owned approval workflows.
|
|
20
|
+
|
|
21
|
+
AIOC `0.2.0` adds implemented runtime utilities and an experimental Agent Harness Descriptor surface. The core runtime remains compatibility-managed; descriptor shape and loader helpers may still evolve across `0.x` minor releases with explicit migration guidance.
|
|
22
|
+
AIOC `0.2.1` realigns the `0.2.x` package line with the current `main` history after `0.2.0` was published from the descriptor release branch.
|
|
17
23
|
|
|
18
24
|
- Release notes: `CHANGELOG.md`
|
|
19
25
|
- Historical beta contract snapshot: `docs/BETA-CONTRACT.md`
|
|
@@ -94,6 +100,7 @@ console.log(result.finalOutput);
|
|
|
94
100
|
- handoffs via `Agent({ handoffs: [...] })`
|
|
95
101
|
- `run(...)` with streaming support (`stream` defaults to `false`)
|
|
96
102
|
- policy helpers `allow(...)` / `deny(...)` / `requireApproval(...)`
|
|
103
|
+
- approval evidence helpers `createApprovalRequestSeed(...)`, `toApprovedProposalHashes(...)`, `toActiveApprovalGrantMap(...)`
|
|
97
104
|
- provider setup helpers `setupMistral(...)`, `setupOpenAI(...)`, `setupProvider(...)`
|
|
98
105
|
- run logger hook `run(..., { logger })`
|
|
99
106
|
- run record hook `run(..., { record })`
|
|
@@ -102,6 +109,16 @@ console.log(result.finalOutput);
|
|
|
102
109
|
- thread history utilities `toThreadHistory(...)`, `appendUserMessage(...)`, `replaceThreadHistory(...)`, `applyRunResultHistory(...)`
|
|
103
110
|
- JSON helper `toJsonValue(...)`
|
|
104
111
|
|
|
112
|
+
## Experimental 0.2.x Surface
|
|
113
|
+
|
|
114
|
+
- `buildAgentHarness(...)`
|
|
115
|
+
- `hashAgentHarnessDescriptor(...)`
|
|
116
|
+
- `loadAgentHarnessDescriptor(...)`
|
|
117
|
+
- `loadAgentHarnessDescriptorFromFile(...)`
|
|
118
|
+
- `AgentHarnessDescriptor` and related descriptor types
|
|
119
|
+
|
|
120
|
+
The Agent Harness Descriptor is included in the `0.2.x` line as an experimental `aioc.agent_graph.v0` descriptor surface. Use it for controlled configuration, examples, and evaluation harnesses; keep executable tools, policies, providers, persistence, approvals, and deployment configuration in application code.
|
|
121
|
+
|
|
105
122
|
## Policy Gate (Minimal)
|
|
106
123
|
|
|
107
124
|
```ts
|
|
@@ -262,10 +279,11 @@ AIOC adopts the following non-negotiable principles:
|
|
|
262
279
|
- `docs/RFC-0003-run-record-audit-trail-and-persistence.md` (`Accepted`)
|
|
263
280
|
- `docs/RFC-0004-policy-outcomes-and-approval-model.md` (`Accepted`)
|
|
264
281
|
- `docs/RFC-0005-suspended-proposals-and-approval-lifecycle.md` (`Accepted`)
|
|
265
|
-
- `docs/RFC-0006-approval-evidence-helpers.md` (`
|
|
282
|
+
- `docs/RFC-0006-approval-evidence-helpers.md` (`Accepted`)
|
|
266
283
|
- `docs/RFC-0007-thread-state-utilities.md` (`Accepted`)
|
|
267
284
|
- `docs/RFC-0008-run-stream-consumer-utilities.md` (`Accepted`)
|
|
268
285
|
- `docs/RFC-0009-governance-events-and-exporters.md` (`Experimental`)
|
|
286
|
+
- `docs/RFC-0010-policy-composition-helpers.md` (`Draft`)
|
|
269
287
|
- `docs/RFC-0011-agent-harness-descriptor.md` (`Experimental`)
|
|
270
288
|
- `docs/PRIVACY-BASELINE.md`
|
|
271
289
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SuspendedProposal } from "./run-record";
|
|
2
|
+
export interface ApprovalGrant {
|
|
3
|
+
proposalHash: string;
|
|
4
|
+
approvedAt: string;
|
|
5
|
+
expiresAt?: string;
|
|
6
|
+
revokedAt?: string;
|
|
7
|
+
metadata?: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
export interface ApprovalRequestSeed {
|
|
10
|
+
proposalHash: string;
|
|
11
|
+
kind: "tool" | "handoff";
|
|
12
|
+
reason: string;
|
|
13
|
+
publicReason?: string;
|
|
14
|
+
policyVersion?: string;
|
|
15
|
+
expiresAt?: string;
|
|
16
|
+
resourceName: string;
|
|
17
|
+
canonicalPayloadJson: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function createApprovalRequestSeed(proposal: SuspendedProposal): ApprovalRequestSeed;
|
|
20
|
+
export declare function isApprovalGrantActive(grant: ApprovalGrant, now?: string): boolean;
|
|
21
|
+
export declare function findActiveApprovalGrant(proposalHash: string, grants: readonly ApprovalGrant[], now?: string): ApprovalGrant | null;
|
|
22
|
+
export declare function toActiveApprovalGrantMap(grants: readonly ApprovalGrant[], now?: string): Record<string, ApprovalGrant>;
|
|
23
|
+
export declare function toApprovedProposalHashes(grants: readonly ApprovalGrant[], now?: string): string[];
|
|
24
|
+
//# sourceMappingURL=approval-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-helpers.d.ts","sourceRoot":"","sources":["../src/approval-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAsCD,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,iBAAiB,GAC1B,mBAAmB,CAoBrB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,aAAa,EACpB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAYT;AAED,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,GAAG,CAAC,EAAE,MAAM,GACX,aAAa,GAAG,IAAI,CAgBtB;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,GAAG,CAAC,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAe/B;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,GAAG,CAAC,EAAE,MAAM,GACX,MAAM,EAAE,CAEV"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createApprovalRequestSeed = createApprovalRequestSeed;
|
|
4
|
+
exports.isApprovalGrantActive = isApprovalGrantActive;
|
|
5
|
+
exports.findActiveApprovalGrant = findActiveApprovalGrant;
|
|
6
|
+
exports.toActiveApprovalGrantMap = toActiveApprovalGrantMap;
|
|
7
|
+
exports.toApprovedProposalHashes = toApprovedProposalHashes;
|
|
8
|
+
function parseTimestamp(value, label) {
|
|
9
|
+
const timestamp = Date.parse(value);
|
|
10
|
+
if (Number.isNaN(timestamp)) {
|
|
11
|
+
throw new Error(`${label} must be a valid timestamp.`);
|
|
12
|
+
}
|
|
13
|
+
return timestamp;
|
|
14
|
+
}
|
|
15
|
+
function getNowTimestamp(now) {
|
|
16
|
+
return parseTimestamp(now ?? new Date().toISOString(), "now");
|
|
17
|
+
}
|
|
18
|
+
function isGrantNewer(candidate, current) {
|
|
19
|
+
return (parseTimestamp(candidate.approvedAt, "grant.approvedAt") >
|
|
20
|
+
parseTimestamp(current.approvedAt, "grant.approvedAt"));
|
|
21
|
+
}
|
|
22
|
+
function getProposalMetadata(proposal) {
|
|
23
|
+
return {
|
|
24
|
+
...(typeof proposal.publicReason !== "undefined"
|
|
25
|
+
? { publicReason: proposal.publicReason }
|
|
26
|
+
: {}),
|
|
27
|
+
...(typeof proposal.policyVersion !== "undefined"
|
|
28
|
+
? { policyVersion: proposal.policyVersion }
|
|
29
|
+
: {}),
|
|
30
|
+
...(typeof proposal.expiresAt !== "undefined"
|
|
31
|
+
? { expiresAt: proposal.expiresAt }
|
|
32
|
+
: {}),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function createApprovalRequestSeed(proposal) {
|
|
36
|
+
if (proposal.kind === "tool") {
|
|
37
|
+
return {
|
|
38
|
+
proposalHash: proposal.proposalHash,
|
|
39
|
+
kind: proposal.kind,
|
|
40
|
+
reason: proposal.reason,
|
|
41
|
+
...getProposalMetadata(proposal),
|
|
42
|
+
resourceName: proposal.toolName,
|
|
43
|
+
canonicalPayloadJson: proposal.argsCanonicalJson,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
proposalHash: proposal.proposalHash,
|
|
48
|
+
kind: proposal.kind,
|
|
49
|
+
reason: proposal.reason,
|
|
50
|
+
...getProposalMetadata(proposal),
|
|
51
|
+
resourceName: proposal.toAgentName,
|
|
52
|
+
canonicalPayloadJson: proposal.payloadCanonicalJson,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function isApprovalGrantActive(grant, now) {
|
|
56
|
+
if (typeof grant.revokedAt !== "undefined") {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (typeof grant.expiresAt === "undefined") {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return (parseTimestamp(grant.expiresAt, "grant.expiresAt") >= getNowTimestamp(now));
|
|
63
|
+
}
|
|
64
|
+
function findActiveApprovalGrant(proposalHash, grants, now) {
|
|
65
|
+
let match = null;
|
|
66
|
+
for (const grant of grants) {
|
|
67
|
+
if (grant.proposalHash !== proposalHash) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (!isApprovalGrantActive(grant, now)) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (!match || isGrantNewer(grant, match)) {
|
|
74
|
+
match = grant;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return match;
|
|
78
|
+
}
|
|
79
|
+
function toActiveApprovalGrantMap(grants, now) {
|
|
80
|
+
const grantMap = {};
|
|
81
|
+
for (const grant of grants) {
|
|
82
|
+
if (!isApprovalGrantActive(grant, now)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const current = grantMap[grant.proposalHash];
|
|
86
|
+
if (!current || isGrantNewer(grant, current)) {
|
|
87
|
+
grantMap[grant.proposalHash] = grant;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return grantMap;
|
|
91
|
+
}
|
|
92
|
+
function toApprovedProposalHashes(grants, now) {
|
|
93
|
+
return Object.keys(toActiveApprovalGrantMap(grants, now));
|
|
94
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface DescriptorPathContext {
|
|
2
|
+
descriptorDir: string;
|
|
3
|
+
descriptorLabel: string;
|
|
4
|
+
rootDir: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ResolvedPromptFile {
|
|
7
|
+
rawPath: string;
|
|
8
|
+
resolvedPath: string;
|
|
9
|
+
}
|
|
10
|
+
export interface LoadedDescriptorFile {
|
|
11
|
+
context: DescriptorPathContext;
|
|
12
|
+
descriptorLabel: string;
|
|
13
|
+
rootRealPath: string;
|
|
14
|
+
yaml: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function assertNonEmptyString(value: unknown, label: string): asserts value is string;
|
|
17
|
+
export declare function assertPromptFilePath(value: unknown, label: string): asserts value is string;
|
|
18
|
+
export declare function assertPromptFilePathList(value: unknown, label: string): asserts value is string[];
|
|
19
|
+
export declare function resolvePromptFilePath(rawPath: string, context: DescriptorPathContext, label: string): ResolvedPromptFile;
|
|
20
|
+
export declare function createPathContext(options: {
|
|
21
|
+
descriptorPath?: string;
|
|
22
|
+
rootDir?: string;
|
|
23
|
+
}): DescriptorPathContext;
|
|
24
|
+
export declare function createPromptMap(promptMap: Record<string, string>, context: DescriptorPathContext): Map<string, string>;
|
|
25
|
+
export declare function loadDescriptorFile(descriptorPath: string, options?: {
|
|
26
|
+
rootDir?: string;
|
|
27
|
+
}): Promise<LoadedDescriptorFile>;
|
|
28
|
+
export declare function readResolvedPromptFiles(files: ResolvedPromptFile[], label: string, rootRealPath: string): Promise<string[]>;
|
|
29
|
+
//# sourceMappingURL=harness-descriptor-loader-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-descriptor-loader-paths.d.ts","sourceRoot":"","sources":["../src/harness-descriptor-loader-paths.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,qBAAqB,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAKD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,KAAK,IAAI,MAAM,CAIzB;AAmCD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,KAAK,IAAI,MAAM,CAEzB;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,KAAK,IAAI,MAAM,EAAE,CAQ3B;AAiBD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE,MAAM,GACZ,kBAAkB,CAOpB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,qBAAqB,CAaxB;AAED,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,OAAO,EAAE,qBAAqB,GAC7B,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBrB;AAED,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACjC,OAAO,CAAC,oBAAoB,CAAC,CA8B/B;AAED,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,kBAAkB,EAAE,EAC3B,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CAUnB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertNonEmptyString = assertNonEmptyString;
|
|
4
|
+
exports.assertPromptFilePath = assertPromptFilePath;
|
|
5
|
+
exports.assertPromptFilePathList = assertPromptFilePathList;
|
|
6
|
+
exports.resolvePromptFilePath = resolvePromptFilePath;
|
|
7
|
+
exports.createPathContext = createPathContext;
|
|
8
|
+
exports.createPromptMap = createPromptMap;
|
|
9
|
+
exports.loadDescriptorFile = loadDescriptorFile;
|
|
10
|
+
exports.readResolvedPromptFiles = readResolvedPromptFiles;
|
|
11
|
+
const promises_1 = require("node:fs/promises");
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
13
|
+
const URL_LIKE_PATH = /^[A-Za-z][A-Za-z0-9+.-]*:\/\//;
|
|
14
|
+
const GLOB_LIKE_PATH = /[*?[\]{}]/;
|
|
15
|
+
function assertNonEmptyString(value, label) {
|
|
16
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
17
|
+
throw new Error(`${label} must be a non-empty string.`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function assertPathInsideRoot(path, rootDir, label) {
|
|
21
|
+
const relativePath = (0, node_path_1.relative)(rootDir, path);
|
|
22
|
+
if (relativePath === "" ||
|
|
23
|
+
relativePath === ".." ||
|
|
24
|
+
relativePath.startsWith(`..${node_path_1.sep}`) ||
|
|
25
|
+
(0, node_path_1.isAbsolute)(relativePath)) {
|
|
26
|
+
throw new Error(`${label} must resolve inside rootDir "${rootDir}".`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function assertSafePath(value, label, options) {
|
|
30
|
+
assertNonEmptyString(value, label);
|
|
31
|
+
if (value.includes("\0")) {
|
|
32
|
+
throw new Error(`${label} must not contain null bytes.`);
|
|
33
|
+
}
|
|
34
|
+
if (URL_LIKE_PATH.test(value)) {
|
|
35
|
+
throw new Error(`${label} must not be a remote URL.`);
|
|
36
|
+
}
|
|
37
|
+
if (!options.allowAbsolute && (0, node_path_1.isAbsolute)(value)) {
|
|
38
|
+
throw new Error(`${label} must be relative to the descriptor file.`);
|
|
39
|
+
}
|
|
40
|
+
if (GLOB_LIKE_PATH.test(value)) {
|
|
41
|
+
throw new Error(`${label} must not use globbing characters.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function assertPromptFilePath(value, label) {
|
|
45
|
+
assertSafePath(value, label, { allowAbsolute: false });
|
|
46
|
+
}
|
|
47
|
+
function assertPromptFilePathList(value, label) {
|
|
48
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
49
|
+
throw new Error(`${label} must be a non-empty array of strings.`);
|
|
50
|
+
}
|
|
51
|
+
for (const [index, path] of value.entries()) {
|
|
52
|
+
assertPromptFilePath(path, `${label}[${index}]`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function resolveInsideRoot(rawPath, context, label, options) {
|
|
56
|
+
assertSafePath(rawPath, label, options);
|
|
57
|
+
const resolvedPath = (0, node_path_1.isAbsolute)(rawPath)
|
|
58
|
+
? (0, node_path_1.resolve)(rawPath)
|
|
59
|
+
: (0, node_path_1.resolve)(context.descriptorDir, rawPath);
|
|
60
|
+
assertPathInsideRoot(resolvedPath, context.rootDir, label);
|
|
61
|
+
return resolvedPath;
|
|
62
|
+
}
|
|
63
|
+
function resolvePromptFilePath(rawPath, context, label) {
|
|
64
|
+
return {
|
|
65
|
+
rawPath,
|
|
66
|
+
resolvedPath: resolveInsideRoot(rawPath, context, label, {
|
|
67
|
+
allowAbsolute: false,
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function createPathContext(options) {
|
|
72
|
+
const descriptorPath = options.descriptorPath
|
|
73
|
+
? (0, node_path_1.resolve)(options.descriptorPath)
|
|
74
|
+
: undefined;
|
|
75
|
+
const descriptorDir = descriptorPath
|
|
76
|
+
? (0, node_path_1.dirname)(descriptorPath)
|
|
77
|
+
: (0, node_path_1.resolve)(options.rootDir ?? process.cwd());
|
|
78
|
+
const rootDir = (0, node_path_1.resolve)(options.rootDir ?? descriptorDir);
|
|
79
|
+
return {
|
|
80
|
+
descriptorDir,
|
|
81
|
+
descriptorLabel: descriptorPath ?? "<inline descriptor>",
|
|
82
|
+
rootDir,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function createPromptMap(promptMap, context) {
|
|
86
|
+
const normalized = new Map();
|
|
87
|
+
for (const [rawPath, content] of Object.entries(promptMap)) {
|
|
88
|
+
if (typeof content !== "string") {
|
|
89
|
+
throw new Error(`Prompt map entry "${rawPath}" must be a string.`);
|
|
90
|
+
}
|
|
91
|
+
const resolvedPath = resolveInsideRoot(rawPath, context, `Prompt map key "${rawPath}"`, { allowAbsolute: true });
|
|
92
|
+
normalized.set(resolvedPath, content);
|
|
93
|
+
}
|
|
94
|
+
return normalized;
|
|
95
|
+
}
|
|
96
|
+
async function loadDescriptorFile(descriptorPath, options = {}) {
|
|
97
|
+
assertNonEmptyString(descriptorPath, "Harness descriptor path");
|
|
98
|
+
const resolvedDescriptorPath = (0, node_path_1.resolve)(descriptorPath);
|
|
99
|
+
const descriptorDir = (0, node_path_1.dirname)(resolvedDescriptorPath);
|
|
100
|
+
const rootDir = (0, node_path_1.resolve)(options.rootDir ?? descriptorDir);
|
|
101
|
+
const context = createPathContext({
|
|
102
|
+
descriptorPath: resolvedDescriptorPath,
|
|
103
|
+
rootDir,
|
|
104
|
+
});
|
|
105
|
+
assertPathInsideRoot(resolvedDescriptorPath, rootDir, "Harness descriptor path");
|
|
106
|
+
const rootRealPath = await (0, promises_1.realpath)(rootDir);
|
|
107
|
+
const descriptorRealPath = await (0, promises_1.realpath)(resolvedDescriptorPath);
|
|
108
|
+
assertPathInsideRoot(descriptorRealPath, rootRealPath, "Harness descriptor path");
|
|
109
|
+
return {
|
|
110
|
+
context,
|
|
111
|
+
descriptorLabel: descriptorRealPath,
|
|
112
|
+
rootRealPath,
|
|
113
|
+
yaml: await (0, promises_1.readFile)(descriptorRealPath, "utf8"),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
async function readResolvedPromptFiles(files, label, rootRealPath) {
|
|
117
|
+
const contents = [];
|
|
118
|
+
for (const file of files) {
|
|
119
|
+
const promptRealPath = await (0, promises_1.realpath)(file.resolvedPath);
|
|
120
|
+
assertPathInsideRoot(promptRealPath, rootRealPath, `${label} prompt file`);
|
|
121
|
+
contents.push(await (0, promises_1.readFile)(promptRealPath, "utf8"));
|
|
122
|
+
}
|
|
123
|
+
return contents;
|
|
124
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AgentHarnessDescriptor } from "./harness-descriptor";
|
|
2
|
+
export type AgentHarnessPromptMap = Record<string, string>;
|
|
3
|
+
export interface LoadAgentHarnessDescriptorOptions {
|
|
4
|
+
descriptorPath?: string;
|
|
5
|
+
rootDir?: string;
|
|
6
|
+
promptMap?: AgentHarnessPromptMap;
|
|
7
|
+
}
|
|
8
|
+
export interface LoadAgentHarnessDescriptorFromFileOptions {
|
|
9
|
+
rootDir?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function loadAgentHarnessDescriptor(yaml: string, optionsOrPromptMap?: LoadAgentHarnessDescriptorOptions | AgentHarnessPromptMap): AgentHarnessDescriptor;
|
|
12
|
+
export declare function loadAgentHarnessDescriptorFromFile(descriptorPath: string, options?: LoadAgentHarnessDescriptorFromFileOptions): Promise<AgentHarnessDescriptor>;
|
|
13
|
+
//# sourceMappingURL=harness-descriptor-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-descriptor-loader.d.ts","sourceRoot":"","sources":["../src/harness-descriptor-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EAEvB,MAAM,sBAAsB,CAAC;AAa9B,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAuC3D,MAAM,WAAW,iCAAiC;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,qBAAqB,CAAC;CACnC;AAED,MAAM,WAAW,yCAAyC;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA+ND,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,kBAAkB,CAAC,EACf,iCAAiC,GACjC,qBAAqB,GACxB,sBAAsB,CAyBxB;AAED,wBAAsB,kCAAkC,CACtD,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,yCAA8C,GACtD,OAAO,CAAC,sBAAsB,CAAC,CAkBjC"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadAgentHarnessDescriptor = loadAgentHarnessDescriptor;
|
|
4
|
+
exports.loadAgentHarnessDescriptorFromFile = loadAgentHarnessDescriptorFromFile;
|
|
5
|
+
const js_yaml_1 = require("js-yaml");
|
|
6
|
+
const harness_descriptor_loader_paths_1 = require("./harness-descriptor-loader-paths");
|
|
7
|
+
function isPlainObject(value) {
|
|
8
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function normalizeOptions(optionsOrPromptMap) {
|
|
11
|
+
if (!optionsOrPromptMap) {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
if (Object.prototype.hasOwnProperty.call(optionsOrPromptMap, "descriptorPath") ||
|
|
15
|
+
Object.prototype.hasOwnProperty.call(optionsOrPromptMap, "rootDir") ||
|
|
16
|
+
Object.prototype.hasOwnProperty.call(optionsOrPromptMap, "promptMap")) {
|
|
17
|
+
return optionsOrPromptMap;
|
|
18
|
+
}
|
|
19
|
+
return { promptMap: optionsOrPromptMap };
|
|
20
|
+
}
|
|
21
|
+
function parseDescriptorYaml(yaml, descriptorLabel) {
|
|
22
|
+
const parsed = (0, js_yaml_1.load)(yaml);
|
|
23
|
+
if (!isPlainObject(parsed)) {
|
|
24
|
+
throw new Error(`Invalid harness descriptor YAML: ${descriptorLabel}`);
|
|
25
|
+
}
|
|
26
|
+
return parsed;
|
|
27
|
+
}
|
|
28
|
+
function collectInstructionFileReferences(descriptor, context) {
|
|
29
|
+
const references = [];
|
|
30
|
+
const defaultReference = createInstructionFileReference(descriptor.agent_defaults, "Harness descriptor agent_defaults", context);
|
|
31
|
+
if (defaultReference) {
|
|
32
|
+
references.push(defaultReference);
|
|
33
|
+
}
|
|
34
|
+
if (!isPlainObject(descriptor.agents)) {
|
|
35
|
+
return references;
|
|
36
|
+
}
|
|
37
|
+
for (const [agentId, agentDescriptor] of Object.entries(descriptor.agents)) {
|
|
38
|
+
const agentReference = createInstructionFileReference(agentDescriptor, `Harness descriptor agent "${agentId}"`, context);
|
|
39
|
+
if (agentReference) {
|
|
40
|
+
references.push(agentReference);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return references;
|
|
44
|
+
}
|
|
45
|
+
function createInstructionFileReference(value, label, context) {
|
|
46
|
+
if (!isPlainObject(value)) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
const input = readInstructionFilesInput(value, label);
|
|
50
|
+
if (!input) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
target: value,
|
|
55
|
+
label,
|
|
56
|
+
files: input.paths.map((filePath, index) => ({
|
|
57
|
+
...(0, harness_descriptor_loader_paths_1.resolvePromptFilePath)(filePath, context, input.paths.length === 1 ? input.label : `${input.label}[${index}]`),
|
|
58
|
+
})),
|
|
59
|
+
appendInlineInstructions: input.appendInlineInstructions,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function readInstructionFilesInput(value, label) {
|
|
63
|
+
const hasInstructionFile = hasDefined(value, "instructions_file");
|
|
64
|
+
const hasInstructionFiles = hasDefined(value, "instructions_files");
|
|
65
|
+
if (!hasInstructionFile && !hasInstructionFiles) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
assertInstructionFileFields(value, label, {
|
|
69
|
+
hasInstructionFile,
|
|
70
|
+
hasInstructionFiles,
|
|
71
|
+
});
|
|
72
|
+
if (hasInstructionFile) {
|
|
73
|
+
const fileLabel = `${label}.instructions_file`;
|
|
74
|
+
const rawPath = value.instructions_file;
|
|
75
|
+
(0, harness_descriptor_loader_paths_1.assertPromptFilePath)(rawPath, fileLabel);
|
|
76
|
+
return {
|
|
77
|
+
paths: [rawPath],
|
|
78
|
+
label: fileLabel,
|
|
79
|
+
appendInlineInstructions: false,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const filesLabel = `${label}.instructions_files`;
|
|
83
|
+
const rawPaths = value.instructions_files;
|
|
84
|
+
(0, harness_descriptor_loader_paths_1.assertPromptFilePathList)(rawPaths, filesLabel);
|
|
85
|
+
return {
|
|
86
|
+
paths: rawPaths,
|
|
87
|
+
label: filesLabel,
|
|
88
|
+
appendInlineInstructions: true,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function hasDefined(value, key) {
|
|
92
|
+
return key in value && typeof value[key] !== "undefined";
|
|
93
|
+
}
|
|
94
|
+
function assertInstructionFileFields(value, label, fields) {
|
|
95
|
+
const { hasInstructionFile, hasInstructionFiles } = fields;
|
|
96
|
+
if (hasInstructionFile && hasInstructionFiles) {
|
|
97
|
+
throw new Error(`${label}.instructions_file and ${label}.instructions_files are mutually exclusive.`);
|
|
98
|
+
}
|
|
99
|
+
if (hasInstructionFile && typeof value.instructions !== "undefined") {
|
|
100
|
+
throw new Error(`${label}.instructions and ${label}.instructions_file are mutually exclusive.`);
|
|
101
|
+
}
|
|
102
|
+
if (hasInstructionFiles &&
|
|
103
|
+
typeof value.instructions !== "undefined" &&
|
|
104
|
+
typeof value.instructions !== "string") {
|
|
105
|
+
throw new Error(`${label}.instructions must be a string when used with ${label}.instructions_files.`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function materializeInstructionReference(reference, contents) {
|
|
109
|
+
const parts = [...contents];
|
|
110
|
+
const inlineInstructions = reference.target.instructions;
|
|
111
|
+
if (reference.appendInlineInstructions &&
|
|
112
|
+
typeof inlineInstructions === "string" &&
|
|
113
|
+
inlineInstructions.length > 0) {
|
|
114
|
+
parts.push(inlineInstructions);
|
|
115
|
+
}
|
|
116
|
+
reference.target.instructions = parts.join("\n\n");
|
|
117
|
+
delete reference.target.instructions_file;
|
|
118
|
+
delete reference.target.instructions_files;
|
|
119
|
+
}
|
|
120
|
+
function readPromptMapContents(reference, promptMap) {
|
|
121
|
+
return reference.files.map((file) => {
|
|
122
|
+
const content = promptMap.get(file.resolvedPath);
|
|
123
|
+
if (typeof content === "undefined") {
|
|
124
|
+
throw new Error(`Missing promptMap entry for ${reference.label} prompt file "${file.rawPath}".`);
|
|
125
|
+
}
|
|
126
|
+
return content;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function loadAgentHarnessDescriptor(yaml, optionsOrPromptMap) {
|
|
130
|
+
const options = normalizeOptions(optionsOrPromptMap);
|
|
131
|
+
const context = (0, harness_descriptor_loader_paths_1.createPathContext)(options);
|
|
132
|
+
const promptMap = options.promptMap
|
|
133
|
+
? (0, harness_descriptor_loader_paths_1.createPromptMap)(options.promptMap, context)
|
|
134
|
+
: undefined;
|
|
135
|
+
const descriptor = parseDescriptorYaml(yaml, context.descriptorLabel);
|
|
136
|
+
const references = collectInstructionFileReferences(descriptor, context);
|
|
137
|
+
if (references.length > 0 && !promptMap) {
|
|
138
|
+
throw new Error("loadAgentHarnessDescriptor(...) requires promptMap when the descriptor uses instructions_file or instructions_files. Use loadAgentHarnessDescriptorFromFile(...) to read prompt files from disk.");
|
|
139
|
+
}
|
|
140
|
+
if (!promptMap) {
|
|
141
|
+
return descriptor;
|
|
142
|
+
}
|
|
143
|
+
for (const reference of references) {
|
|
144
|
+
const contents = readPromptMapContents(reference, promptMap);
|
|
145
|
+
materializeInstructionReference(reference, contents);
|
|
146
|
+
}
|
|
147
|
+
return descriptor;
|
|
148
|
+
}
|
|
149
|
+
async function loadAgentHarnessDescriptorFromFile(descriptorPath, options = {}) {
|
|
150
|
+
const loaded = await (0, harness_descriptor_loader_paths_1.loadDescriptorFile)(descriptorPath, options);
|
|
151
|
+
const descriptor = parseDescriptorYaml(loaded.yaml, loaded.descriptorLabel);
|
|
152
|
+
const references = collectInstructionFileReferences(descriptor, loaded.context);
|
|
153
|
+
for (const reference of references) {
|
|
154
|
+
const contents = await (0, harness_descriptor_loader_paths_1.readResolvedPromptFiles)(reference.files, reference.label, loaded.rootRealPath);
|
|
155
|
+
materializeInstructionReference(reference, contents);
|
|
156
|
+
}
|
|
157
|
+
return descriptor;
|
|
158
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-descriptor.d.ts","sourceRoot":"","sources":["../src/harness-descriptor.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"harness-descriptor.d.ts","sourceRoot":"","sources":["../src/harness-descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAA0B,MAAM,SAAS,CAAC;AAExD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,iCAAiC;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,4BAA4B,GACpC,OAAO,GACP,iCAAiC,CAAC;AAEtC,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,sBAAsB;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,OAAO,EAAE,wBAAwB,CAAC;IAClC,OAAO,CAAC,EAAE,wBAAwB,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC9C,cAAc,CAAC,EAAE,IAAI,CACnB,sBAAsB,EACtB,OAAO,GAAG,eAAe,GAAG,cAAc,CAC3C,CAAC;IACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,oBAAoB,CAAC,QAAQ,GAAG,OAAO;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY,CAAC,QAAQ,GAAG,OAAO;IAC9C,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5B,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,UAAU,EAAE,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1D,aAAa,CAAC,KAAK,CAAC,EAAE,yBAAyB,GAAG,QAAQ,CAAC;CAC5D;AA4XD,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,sBAAsB,GACjC,MAAM,CAER;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,GAAG,OAAO,EAClD,UAAU,EAAE,sBAAsB,EAClC,QAAQ,GAAE,oBAAoB,CAAC,QAAQ,CAAM,GAC5C,YAAY,CAAC,QAAQ,CAAC,CAqExB"}
|
|
@@ -44,11 +44,23 @@ function validateDescriptorShape(descriptor) {
|
|
|
44
44
|
assertOptionalPlainObject(descriptor.context, "Harness descriptor context");
|
|
45
45
|
assertOptionalPlainObject(descriptor.context?.fields, "Harness descriptor context.fields");
|
|
46
46
|
assertOptionalPlainObject(descriptor.context?.references, "Harness descriptor context.references");
|
|
47
|
+
assertNoUnresolvedInstructionFile(descriptor.agent_defaults, "Harness descriptor agent_defaults");
|
|
48
|
+
for (const [agentId, agentDescriptor] of Object.entries(descriptor.agents)) {
|
|
49
|
+
assertPlainObject(agentDescriptor, `Harness descriptor agent "${agentId}"`);
|
|
50
|
+
assertNoUnresolvedInstructionFile(agentDescriptor, `Harness descriptor agent "${agentId}"`);
|
|
51
|
+
}
|
|
47
52
|
for (const [toolId, toolDescriptor] of Object.entries(descriptor.tools ?? {})) {
|
|
48
53
|
assertPlainObject(toolDescriptor, `Harness descriptor tool "${toolId}"`);
|
|
49
54
|
assertNonEmptyString(toolDescriptor.target, `Harness descriptor tool "${toolId}".target`);
|
|
50
55
|
}
|
|
51
56
|
}
|
|
57
|
+
function assertNoUnresolvedInstructionFile(value, label) {
|
|
58
|
+
if (!isPlainObject(value) ||
|
|
59
|
+
(!("instructions_file" in value) && !("instructions_files" in value))) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
throw new Error(`${label}.instructions_file/instructions_files must be materialized by loadAgentHarnessDescriptor(...) before buildAgentHarness(...).`);
|
|
63
|
+
}
|
|
52
64
|
function normalizePromptPath(path, label) {
|
|
53
65
|
const segments = path
|
|
54
66
|
.split(".")
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from "./agent";
|
|
2
|
+
export * from "./approval-helpers";
|
|
2
3
|
export * from "./config";
|
|
3
4
|
export * from "./errors";
|
|
4
5
|
export * from "./guardrails";
|
|
5
6
|
export * from "./harness-descriptor";
|
|
7
|
+
export * from "./harness-descriptor-loader";
|
|
6
8
|
export * from "./json";
|
|
7
9
|
export * from "./logger";
|
|
8
10
|
export * from "./messages";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,OAAO,CAAC;AACtB,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,OAAO,CAAC;AACtB,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -15,10 +15,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./agent"), exports);
|
|
18
|
+
__exportStar(require("./approval-helpers"), exports);
|
|
18
19
|
__exportStar(require("./config"), exports);
|
|
19
20
|
__exportStar(require("./errors"), exports);
|
|
20
21
|
__exportStar(require("./guardrails"), exports);
|
|
21
22
|
__exportStar(require("./harness-descriptor"), exports);
|
|
23
|
+
__exportStar(require("./harness-descriptor-loader"), exports);
|
|
22
24
|
__exportStar(require("./json"), exports);
|
|
23
25
|
__exportStar(require("./logger"), exports);
|
|
24
26
|
__exportStar(require("./messages"), exports);
|