@axiastudio/aioc 0.2.0-next.2 → 0.2.0

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
@@ -15,6 +15,8 @@ The core runtime surface is compatibility-managed. Breaking changes to the stabl
15
15
 
16
16
  AIOC `0.1.0` stabilizes 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.
17
17
 
18
+ 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.
19
+
18
20
  - Release notes: `CHANGELOG.md`
19
21
  - Historical beta contract snapshot: `docs/BETA-CONTRACT.md`
20
22
  - Historical alpha contract snapshot: `docs/ALPHA-CONTRACT.md`
@@ -102,6 +104,16 @@ console.log(result.finalOutput);
102
104
  - thread history utilities `toThreadHistory(...)`, `appendUserMessage(...)`, `replaceThreadHistory(...)`, `applyRunResultHistory(...)`
103
105
  - JSON helper `toJsonValue(...)`
104
106
 
107
+ ## Experimental 0.2.0 Surface
108
+
109
+ - `buildAgentHarness(...)`
110
+ - `hashAgentHarnessDescriptor(...)`
111
+ - `loadAgentHarnessDescriptor(...)`
112
+ - `loadAgentHarnessDescriptorFromFile(...)`
113
+ - `AgentHarnessDescriptor` and related descriptor types
114
+
115
+ The Agent Harness Descriptor is included in `0.2.0` 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.
116
+
105
117
  ## Policy Gate (Minimal)
106
118
 
107
119
  ```ts
@@ -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":"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"}
@@ -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
@@ -3,6 +3,7 @@ export * from "./config";
3
3
  export * from "./errors";
4
4
  export * from "./guardrails";
5
5
  export * from "./harness-descriptor";
6
+ export * from "./harness-descriptor-loader";
6
7
  export * from "./json";
7
8
  export * from "./logger";
8
9
  export * from "./messages";
@@ -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,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
@@ -19,6 +19,7 @@ __exportStar(require("./config"), exports);
19
19
  __exportStar(require("./errors"), exports);
20
20
  __exportStar(require("./guardrails"), exports);
21
21
  __exportStar(require("./harness-descriptor"), exports);
22
+ __exportStar(require("./harness-descriptor-loader"), exports);
22
23
  __exportStar(require("./json"), exports);
23
24
  __exportStar(require("./logger"), exports);
24
25
  __exportStar(require("./messages"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiastudio/aioc",
3
- "version": "0.2.0-next.2",
3
+ "version": "0.2.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [